mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-06 14:52:34 +02:00
975 lines
30 KiB
C
975 lines
30 KiB
C
/* -*- Mode: c; c-basic-offset: 2 -*-
|
|
*
|
|
* rdf_storage_list.c - RDF Storage in memory as a list implementation
|
|
*
|
|
* Copyright (C) 2000-2008, David Beckett http://www.dajobe.org/
|
|
* Copyright (C) 2000-2004, University of Bristol, UK http://www.bristol.ac.uk/
|
|
*
|
|
* This package is Free Software and part of Redland http://librdf.org/
|
|
*
|
|
* It is licensed under the following three licenses as alternatives:
|
|
* 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
|
|
* 2. GNU General Public License (GPL) V2 or any newer version
|
|
* 3. Apache License, V2.0 or any newer version
|
|
*
|
|
* You may not use this file except in compliance with at least one of
|
|
* the above three licenses.
|
|
*
|
|
* See LICENSE.html or LICENSE.txt at the top of this package for the
|
|
* complete terms and further detail along with the license texts for
|
|
* the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <rdf_config.h>
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#include <win32_rdf_config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h> /* for abort() as used in errors */
|
|
#endif
|
|
#include <sys/types.h>
|
|
|
|
#include <redland.h>
|
|
|
|
|
|
typedef struct
|
|
{
|
|
librdf_list* list;
|
|
|
|
/* If this is non-0, contexts are being used */
|
|
int index_contexts;
|
|
librdf_hash* contexts;
|
|
|
|
} librdf_storage_list_context;
|
|
|
|
|
|
/* These are stored in the list */
|
|
typedef struct
|
|
{
|
|
librdf_statement *statement;
|
|
librdf_node *context;
|
|
} librdf_storage_list_node;
|
|
|
|
|
|
/* prototypes for local functions */
|
|
static int librdf_storage_list_init(librdf_storage* storage, const char *name, librdf_hash* options);
|
|
static int librdf_storage_list_open(librdf_storage* storage, librdf_model* model);
|
|
static int librdf_storage_list_close(librdf_storage* storage);
|
|
static int librdf_storage_list_size(librdf_storage* storage);
|
|
static int librdf_storage_list_add_statement(librdf_storage* storage, librdf_statement* statement);
|
|
static int librdf_storage_list_add_statements(librdf_storage* storage, librdf_stream* statement_stream);
|
|
static int librdf_storage_list_remove_statement(librdf_storage* storage, librdf_statement* statement);
|
|
static int librdf_storage_list_contains_statement(librdf_storage* storage, librdf_statement* statement);
|
|
static librdf_stream* librdf_storage_list_serialise(librdf_storage* storage);
|
|
static librdf_stream* librdf_storage_list_find_statements(librdf_storage* storage, librdf_statement* statement);
|
|
|
|
/* serialising implementing functions */
|
|
static int librdf_storage_list_serialise_end_of_stream(void* context);
|
|
static int librdf_storage_list_serialise_next_statement(void* context);
|
|
static void* librdf_storage_list_serialise_get_statement(void* context, int flags);
|
|
static void librdf_storage_list_serialise_finished(void* context);
|
|
|
|
/* context functions */
|
|
static int librdf_storage_list_context_add_statement(librdf_storage* storage, librdf_node* context_node, librdf_statement* statement);
|
|
static int librdf_storage_list_context_remove_statement(librdf_storage* storage, librdf_node* context_node, librdf_statement* statement);
|
|
static librdf_stream* librdf_storage_list_context_serialise(librdf_storage* storage, librdf_node* context_node);
|
|
|
|
/* context list statement stream methods */
|
|
static int librdf_storage_list_context_serialise_end_of_stream(void* context);
|
|
static int librdf_storage_list_context_serialise_next_statement(void* context);
|
|
static void* librdf_storage_list_context_serialise_get_statement(void* context, int flags);
|
|
static void librdf_storage_list_context_serialise_finished(void* context);
|
|
|
|
/* helper functions for contexts */
|
|
static int librdf_storage_list_node_equals(librdf_storage_list_node *first, librdf_storage_list_node *second);
|
|
|
|
static librdf_iterator* librdf_storage_list_get_contexts(librdf_storage* storage);
|
|
|
|
/* get_context iterator functions */
|
|
static int librdf_storage_list_get_contexts_is_end(void* iterator);
|
|
static int librdf_storage_list_get_contexts_next_method(void* iterator);
|
|
static void* librdf_storage_list_get_contexts_get_method(void* iterator, int);
|
|
static void librdf_storage_list_get_contexts_finished(void* iterator);
|
|
|
|
|
|
static void librdf_storage_list_register_factory(librdf_storage_factory *factory);
|
|
|
|
|
|
|
|
/* functions implementing storage api */
|
|
static int
|
|
librdf_storage_list_init(librdf_storage* storage, const char *name,
|
|
librdf_hash* options)
|
|
{
|
|
librdf_storage_list_context *context=(librdf_storage_list_context*)storage->context;
|
|
int index_contexts=0;
|
|
|
|
if((index_contexts=librdf_hash_get_as_boolean(options, "contexts"))<0)
|
|
index_contexts=0; /* default is no contexts */
|
|
|
|
context->index_contexts=index_contexts;
|
|
|
|
/* no more options, might as well free them now */
|
|
if(options)
|
|
librdf_free_hash(options);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
librdf_storage_list_terminate(librdf_storage* storage)
|
|
{
|
|
/* nop */
|
|
}
|
|
|
|
|
|
/* Helper for comparing list nodes when using contexts */
|
|
static int
|
|
librdf_storage_list_node_equals(librdf_storage_list_node *first,
|
|
librdf_storage_list_node *second)
|
|
{
|
|
if(!librdf_statement_equals(first->statement, second->statement))
|
|
return 0;
|
|
|
|
if(!first->context && !second->context)
|
|
return 1;
|
|
|
|
if(!first->context || !second->context)
|
|
return 0;
|
|
|
|
if(!librdf_node_equals(first->context, second->context))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_open(librdf_storage* storage, librdf_model* model)
|
|
{
|
|
librdf_storage_list_context *context=(librdf_storage_list_context*)storage->context;
|
|
|
|
context->list=librdf_new_list(storage->world);
|
|
if(!context->list)
|
|
return 1;
|
|
|
|
if(context->index_contexts) {
|
|
/* create a new memory hash */
|
|
context->contexts=librdf_new_hash(storage->world, NULL);
|
|
if(librdf_hash_open(context->contexts, NULL, 0, 1, 1, NULL)) {
|
|
librdf_free_list(context->list);
|
|
context->list=NULL;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
librdf_list_set_equals(context->list,
|
|
(int (*)(void*, void*))&librdf_storage_list_node_equals);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_list_close:
|
|
* @storage: the storage
|
|
*
|
|
* .
|
|
*
|
|
* Close the storage list storage, and free all content since there is no
|
|
* persistance.
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
static int
|
|
librdf_storage_list_close(librdf_storage* storage)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
|
|
if(context->list) {
|
|
librdf_storage_list_node* sln;
|
|
while((sln=(librdf_storage_list_node*)librdf_list_pop(context->list))) {
|
|
librdf_free_statement(sln->statement);
|
|
if(sln->context)
|
|
librdf_free_node(sln->context);
|
|
LIBRDF_FREE(librdf_storage_list_node, sln);
|
|
}
|
|
librdf_free_list(context->list);
|
|
context->list=NULL;
|
|
}
|
|
|
|
if(context->index_contexts) {
|
|
if(context->contexts) {
|
|
librdf_free_hash(context->contexts);
|
|
context->contexts=NULL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_size(librdf_storage* storage)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
|
|
return librdf_list_size(context->list);
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_add_statement(librdf_storage* storage, librdf_statement* statement)
|
|
{
|
|
/* Do not add duplicate statements */
|
|
if(librdf_storage_list_contains_statement(storage, statement))
|
|
return 0;
|
|
|
|
return librdf_storage_list_context_add_statement(storage, NULL, statement);
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_add_statements(librdf_storage* storage,
|
|
librdf_stream* statement_stream)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
int status=0;
|
|
|
|
for(; !librdf_stream_end(statement_stream);
|
|
librdf_stream_next(statement_stream)) {
|
|
librdf_statement* statement=librdf_stream_get_object(statement_stream);
|
|
librdf_storage_list_node* sln;
|
|
|
|
if(!statement) {
|
|
status=1;
|
|
break;
|
|
}
|
|
|
|
/* Do not add duplicate statements */
|
|
if(librdf_storage_list_contains_statement(storage, statement))
|
|
continue;
|
|
|
|
sln=(librdf_storage_list_node*)LIBRDF_MALLOC(librdf_storage_list_node, sizeof(librdf_storage_list_node));
|
|
if(!sln) {
|
|
status=1;
|
|
break;
|
|
}
|
|
|
|
/* copy shared statement */
|
|
sln->statement=librdf_new_statement_from_statement(statement);
|
|
if(!sln->statement) {
|
|
LIBRDF_FREE(librdf_storage_list_node, sln);
|
|
status=1;
|
|
break;
|
|
}
|
|
sln->context=NULL;
|
|
librdf_list_add(context->list, sln);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_remove_statement(librdf_storage* storage, librdf_statement* statement)
|
|
{
|
|
return librdf_storage_list_context_remove_statement(storage, NULL, statement);
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_contains_statement(librdf_storage* storage, librdf_statement* statement)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
librdf_storage_list_node sln; /* STATIC */
|
|
sln.statement=statement;
|
|
sln.context=NULL;
|
|
|
|
if(context->index_contexts) {
|
|
/* When we have contexts, we have to use find_statements for contains
|
|
* since we do not know what context node may be stored for a statement
|
|
*/
|
|
librdf_stream *stream=librdf_storage_list_find_statements(storage, statement);
|
|
int status;
|
|
|
|
if(!stream)
|
|
return 0;
|
|
/* librdf_stream_end returns 0 if have more, non-0 at end */
|
|
status=!librdf_stream_end(stream);
|
|
/* convert to 0 if at end (not found) and non-zero otherwise (found) */
|
|
librdf_free_stream(stream);
|
|
return status;
|
|
}
|
|
|
|
|
|
return librdf_list_contains(context->list, &sln);
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
librdf_storage *storage;
|
|
int index_contexts;
|
|
librdf_iterator* iterator;
|
|
} librdf_storage_list_serialise_stream_context;
|
|
|
|
|
|
static librdf_stream*
|
|
librdf_storage_list_serialise(librdf_storage* storage)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
librdf_storage_list_serialise_stream_context* scontext;
|
|
librdf_stream* stream;
|
|
|
|
scontext=(librdf_storage_list_serialise_stream_context*)LIBRDF_CALLOC(librdf_storage_list_serialise_stream_context, 1, sizeof(librdf_storage_list_serialise_stream_context));
|
|
if(!scontext)
|
|
return NULL;
|
|
|
|
scontext->index_contexts=context->index_contexts;
|
|
scontext->iterator=librdf_list_get_iterator(context->list);
|
|
if(!scontext->iterator) {
|
|
LIBRDF_FREE(librdf_storage_list_serialise_stream_context, scontext);
|
|
return librdf_new_empty_stream(storage->world);
|
|
}
|
|
|
|
|
|
scontext->storage=storage;
|
|
librdf_storage_add_reference(scontext->storage);
|
|
|
|
stream=librdf_new_stream(storage->world,
|
|
(void*)scontext,
|
|
&librdf_storage_list_serialise_end_of_stream,
|
|
&librdf_storage_list_serialise_next_statement,
|
|
&librdf_storage_list_serialise_get_statement,
|
|
&librdf_storage_list_serialise_finished);
|
|
if(!stream) {
|
|
librdf_storage_list_serialise_finished((void*)scontext);
|
|
return NULL;
|
|
}
|
|
|
|
return stream;
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_serialise_end_of_stream(void* context)
|
|
{
|
|
librdf_storage_list_serialise_stream_context* scontext=(librdf_storage_list_serialise_stream_context*)context;
|
|
|
|
return librdf_iterator_end(scontext->iterator);
|
|
|
|
}
|
|
|
|
static int
|
|
librdf_storage_list_serialise_next_statement(void* context)
|
|
{
|
|
librdf_storage_list_serialise_stream_context* scontext=(librdf_storage_list_serialise_stream_context*)context;
|
|
|
|
return librdf_iterator_next(scontext->iterator);
|
|
}
|
|
|
|
|
|
static void*
|
|
librdf_storage_list_serialise_get_statement(void* context, int flags)
|
|
{
|
|
librdf_storage_list_serialise_stream_context* scontext=(librdf_storage_list_serialise_stream_context*)context;
|
|
librdf_storage_list_node* sln=(librdf_storage_list_node*)librdf_iterator_get_object(scontext->iterator);
|
|
|
|
switch(flags) {
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
|
|
return sln->statement;
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT:
|
|
if(scontext->index_contexts)
|
|
return sln->context;
|
|
else
|
|
return NULL;
|
|
default:
|
|
librdf_log(scontext->iterator->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"Unknown iterator method flag %d", flags);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
librdf_storage_list_serialise_finished(void* context)
|
|
{
|
|
librdf_storage_list_serialise_stream_context* scontext=(librdf_storage_list_serialise_stream_context*)context;
|
|
|
|
if(scontext->iterator)
|
|
librdf_free_iterator(scontext->iterator);
|
|
|
|
if(scontext->storage)
|
|
librdf_storage_remove_reference(scontext->storage);
|
|
|
|
LIBRDF_FREE(librdf_storage_list_serialise_stream_context, scontext);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_list_find_statements:
|
|
* @storage: the storage
|
|
* @statement: the statement to match
|
|
*
|
|
* .
|
|
*
|
|
* Return a stream of statements matching the given statement (or
|
|
* all statements if NULL). Parts (subject, predicate, object) of the
|
|
* statement can be empty in which case any statement part will match that.
|
|
* Uses #librdf_statement_match to do the matching.
|
|
*
|
|
* Return value: a #librdf_stream or NULL on failure
|
|
**/
|
|
static librdf_stream*
|
|
librdf_storage_list_find_statements(librdf_storage* storage, librdf_statement* statement)
|
|
{
|
|
librdf_stream* stream;
|
|
|
|
statement=librdf_new_statement_from_statement(statement);
|
|
if(!statement)
|
|
return NULL;
|
|
|
|
stream=librdf_storage_list_serialise(storage);
|
|
if(stream) {
|
|
if(librdf_stream_add_map(stream, &librdf_stream_statement_find_map,
|
|
(librdf_stream_map_free_context_handler)&librdf_free_statement,
|
|
(void*)statement)) {
|
|
/* error - stream_add_map failed */
|
|
librdf_free_stream(stream);
|
|
stream=NULL;
|
|
}
|
|
}
|
|
else
|
|
librdf_free_statement(statement);
|
|
|
|
return stream;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_list_context_add_statement:
|
|
* @storage: #librdf_storage object
|
|
* @context_node: #librdf_node object
|
|
* @statement: #librdf_statement statement to add
|
|
*
|
|
* Add a statement to a storage context.
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
static int
|
|
librdf_storage_list_context_add_statement(librdf_storage* storage,
|
|
librdf_node* context_node,
|
|
librdf_statement* statement)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
librdf_hash_datum key, value; /* on stack - not allocated */
|
|
size_t size;
|
|
librdf_storage_list_node* sln;
|
|
int status;
|
|
|
|
if(context_node && !context->index_contexts) {
|
|
librdf_log(storage->world, 0, LIBRDF_LOG_WARN, LIBRDF_FROM_STORAGE, NULL,
|
|
"Storage was created without context support");
|
|
return 1;
|
|
}
|
|
|
|
/* Store statement + node in the storage_list */
|
|
sln=(librdf_storage_list_node*)LIBRDF_MALLOC(librdf_storage_list_node, sizeof(librdf_storage_list_node));
|
|
if(!sln)
|
|
return 1;
|
|
|
|
sln->statement=librdf_new_statement_from_statement(statement);
|
|
if(!sln->statement) {
|
|
LIBRDF_FREE(librdf_storage_list_node, sln);
|
|
return 1;
|
|
}
|
|
if(context->index_contexts && context_node) {
|
|
sln->context=librdf_new_node_from_node(context_node);
|
|
if(!sln->context) {
|
|
librdf_free_statement(sln->statement);
|
|
LIBRDF_FREE(librdf_storage_list_node, sln);
|
|
return 1;
|
|
}
|
|
} else
|
|
sln->context=NULL;
|
|
|
|
status=librdf_list_add(context->list, sln);
|
|
if(status) {
|
|
if(context_node)
|
|
librdf_free_node(sln->context);
|
|
librdf_free_statement(sln->statement);
|
|
LIBRDF_FREE(librdf_storage_list_node, sln);
|
|
return 1;
|
|
}
|
|
|
|
if(!context->index_contexts || !context_node)
|
|
return 0;
|
|
|
|
/* Store (context => statement) in the context hash */
|
|
size=librdf_node_encode(context_node, NULL, 0);
|
|
key.data=(char*)LIBRDF_MALLOC(cstring, size);
|
|
key.size=librdf_node_encode(context_node, (unsigned char*)key.data, size);
|
|
|
|
size=librdf_statement_encode(statement, NULL, 0);
|
|
value.data=(char*)LIBRDF_MALLOC(cstring, size);
|
|
value.size=librdf_statement_encode(statement, (unsigned char*)value.data, size);
|
|
|
|
status=librdf_hash_put(context->contexts, &key, &value);
|
|
LIBRDF_FREE(data, key.data);
|
|
LIBRDF_FREE(data, value.data);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_list_context_remove_statement:
|
|
* @storage: #librdf_storage object
|
|
* @context_node: #librdf_node object
|
|
* @statement: #librdf_statement statement to remove
|
|
*
|
|
* Remove a statement from a storage context.
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
static int
|
|
librdf_storage_list_context_remove_statement(librdf_storage* storage,
|
|
librdf_node* context_node,
|
|
librdf_statement* statement)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
librdf_hash_datum key, value; /* on stack - not allocated */
|
|
librdf_storage_list_node* sln;
|
|
librdf_storage_list_node search_sln; /* on stack - not allocated */
|
|
size_t size;
|
|
int status;
|
|
|
|
if(context_node && !context->index_contexts) {
|
|
librdf_log(storage->world, 0, LIBRDF_LOG_WARN, LIBRDF_FROM_STORAGE, NULL,
|
|
"Storage was created without context support");
|
|
return 1;
|
|
}
|
|
|
|
search_sln.statement=statement;
|
|
search_sln.context=context_node;
|
|
|
|
/* Remove stored statement+context */
|
|
sln=(librdf_storage_list_node*)librdf_list_remove(context->list, &search_sln);
|
|
if(!sln)
|
|
return 1;
|
|
|
|
librdf_free_statement(sln->statement);
|
|
if(sln->context)
|
|
librdf_free_node(sln->context);
|
|
LIBRDF_FREE(librdf_storage_list_node, sln);
|
|
|
|
if(!context->index_contexts || !context_node)
|
|
return 0;
|
|
|
|
/* Remove (context => statement) in the context hash */
|
|
size=librdf_node_encode(context_node, NULL, 0);
|
|
key.data=(char*)LIBRDF_MALLOC(cstring, size);
|
|
key.size=librdf_node_encode(context_node, (unsigned char*)key.data, size);
|
|
|
|
size=librdf_statement_encode(statement, NULL, 0);
|
|
value.data=(char*)LIBRDF_MALLOC(cstring, size);
|
|
value.size=librdf_statement_encode(statement, (unsigned char*)value.data, size);
|
|
|
|
status=librdf_hash_delete(context->contexts, &key, &value);
|
|
LIBRDF_FREE(data, key.data);
|
|
LIBRDF_FREE(data, value.data);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
librdf_storage *storage;
|
|
librdf_iterator* iterator;
|
|
librdf_hash_datum *key;
|
|
librdf_hash_datum *value;
|
|
librdf_statement current; /* static, shared statement */
|
|
librdf_node *context_node;
|
|
char *context_node_data;
|
|
} librdf_storage_list_context_serialise_stream_context;
|
|
|
|
|
|
/**
|
|
* librdf_storage_list_context_serialise:
|
|
* @storage: #librdf_storage object
|
|
* @context_node: #librdf_node object
|
|
*
|
|
* List all statements in a storage context.
|
|
*
|
|
* Return value: #librdf_stream of statements or NULL on failure or context is empty
|
|
**/
|
|
static librdf_stream*
|
|
librdf_storage_list_context_serialise(librdf_storage* storage,
|
|
librdf_node* context_node)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
librdf_storage_list_context_serialise_stream_context* scontext;
|
|
librdf_stream* stream;
|
|
size_t size;
|
|
|
|
if(!context->index_contexts) {
|
|
librdf_log(storage->world, 0, LIBRDF_LOG_WARN, LIBRDF_FROM_STORAGE, NULL,
|
|
"Storage was created without context support");
|
|
return NULL;
|
|
}
|
|
|
|
scontext=(librdf_storage_list_context_serialise_stream_context*)LIBRDF_CALLOC(librdf_storage_list_context_serialise_stream_context, 1, sizeof(librdf_storage_list_context_serialise_stream_context));
|
|
if(!scontext)
|
|
return NULL;
|
|
|
|
librdf_statement_init(storage->world, &scontext->current);
|
|
|
|
scontext->key=librdf_new_hash_datum(storage->world, NULL, 0);
|
|
if(!scontext->key)
|
|
return NULL;
|
|
|
|
scontext->value=librdf_new_hash_datum(storage->world, NULL, 0);
|
|
if(!scontext->value) {
|
|
librdf_free_hash_datum(scontext->key);
|
|
return NULL;
|
|
}
|
|
|
|
scontext->context_node=librdf_new_node_from_node(context_node);
|
|
|
|
size=librdf_node_encode(scontext->context_node, NULL, 0);
|
|
scontext->key->data=scontext->context_node_data=(char*)LIBRDF_MALLOC(cstring, size);
|
|
scontext->key->size=librdf_node_encode(scontext->context_node,
|
|
(unsigned char*)scontext->key->data,
|
|
size);
|
|
|
|
scontext->iterator=librdf_hash_get_all(context->contexts,
|
|
scontext->key, scontext->value);
|
|
if(!scontext->iterator)
|
|
return librdf_new_empty_stream(storage->world);
|
|
|
|
|
|
scontext->storage=storage;
|
|
librdf_storage_add_reference(scontext->storage);
|
|
|
|
stream=librdf_new_stream(storage->world,
|
|
(void*)scontext,
|
|
&librdf_storage_list_context_serialise_end_of_stream,
|
|
&librdf_storage_list_context_serialise_next_statement,
|
|
&librdf_storage_list_context_serialise_get_statement,
|
|
&librdf_storage_list_context_serialise_finished);
|
|
if(!stream) {
|
|
librdf_storage_list_context_serialise_finished((void*)scontext);
|
|
return NULL;
|
|
}
|
|
|
|
return stream;
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_context_serialise_end_of_stream(void* context)
|
|
{
|
|
librdf_storage_list_context_serialise_stream_context* scontext=(librdf_storage_list_context_serialise_stream_context*)context;
|
|
|
|
return librdf_iterator_end(scontext->iterator);
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_context_serialise_next_statement(void* context)
|
|
{
|
|
librdf_storage_list_context_serialise_stream_context* scontext=(librdf_storage_list_context_serialise_stream_context*)context;
|
|
|
|
return librdf_iterator_next(scontext->iterator);
|
|
}
|
|
|
|
|
|
static void*
|
|
librdf_storage_list_context_serialise_get_statement(void* context, int flags)
|
|
{
|
|
librdf_storage_list_context_serialise_stream_context* scontext=(librdf_storage_list_context_serialise_stream_context*)context;
|
|
librdf_hash_datum* v;
|
|
|
|
switch(flags) {
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
|
|
if(!(v=(librdf_hash_datum*)librdf_iterator_get_value(scontext->iterator)))
|
|
return NULL;
|
|
|
|
librdf_statement_clear(&scontext->current);
|
|
|
|
/* decode value content */
|
|
if(!librdf_statement_decode(&scontext->current,
|
|
(unsigned char*)v->data, v->size)) {
|
|
return NULL;
|
|
}
|
|
|
|
return &scontext->current;
|
|
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT:
|
|
return scontext->context_node;
|
|
default:
|
|
librdf_log(scontext->iterator->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"Unknown iterator method flag %d", flags);
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
librdf_storage_list_context_serialise_finished(void* context)
|
|
{
|
|
librdf_storage_list_context_serialise_stream_context* scontext=(librdf_storage_list_context_serialise_stream_context*)context;
|
|
|
|
if(scontext->context_node)
|
|
librdf_free_node(scontext->context_node);
|
|
|
|
if(scontext->iterator)
|
|
librdf_free_iterator(scontext->iterator);
|
|
|
|
if(scontext->key) {
|
|
scontext->key->data=NULL;
|
|
librdf_free_hash_datum(scontext->key);
|
|
}
|
|
|
|
if(scontext->value) {
|
|
scontext->value->data=NULL;
|
|
librdf_free_hash_datum(scontext->value);
|
|
}
|
|
|
|
if(scontext->context_node_data)
|
|
LIBRDF_FREE(cstring, scontext->context_node_data);
|
|
|
|
librdf_statement_clear(&scontext->current);
|
|
|
|
if(scontext->storage)
|
|
librdf_storage_remove_reference(scontext->storage);
|
|
|
|
LIBRDF_FREE(librdf_storage_list_context_serialise_stream_context, scontext);
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
librdf_storage *storage;
|
|
librdf_iterator *iterator;
|
|
librdf_hash_datum *key;
|
|
librdf_node *current;
|
|
} librdf_storage_list_get_contexts_iterator_context;
|
|
|
|
|
|
|
|
static int
|
|
librdf_storage_list_get_contexts_is_end(void* iterator)
|
|
{
|
|
librdf_storage_list_get_contexts_iterator_context* icontext=(librdf_storage_list_get_contexts_iterator_context*)iterator;
|
|
|
|
return librdf_iterator_end(icontext->iterator);
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_list_get_contexts_next_method(void* iterator)
|
|
{
|
|
librdf_storage_list_get_contexts_iterator_context* icontext=(librdf_storage_list_get_contexts_iterator_context*)iterator;
|
|
|
|
return librdf_iterator_next(icontext->iterator);
|
|
}
|
|
|
|
|
|
static void*
|
|
librdf_storage_list_get_contexts_get_method(void* iterator, int flags)
|
|
{
|
|
librdf_storage_list_get_contexts_iterator_context* icontext=(librdf_storage_list_get_contexts_iterator_context*)iterator;
|
|
void *result=NULL;
|
|
librdf_hash_datum* k;
|
|
|
|
switch(flags) {
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
|
|
if(!(k=(librdf_hash_datum*)librdf_iterator_get_key(icontext->iterator)))
|
|
return NULL;
|
|
|
|
if(icontext->current)
|
|
librdf_free_node(icontext->current);
|
|
|
|
/* decode value content */
|
|
icontext->current=librdf_node_decode(icontext->storage->world, NULL,
|
|
(unsigned char*)k->data, k->size);
|
|
result=icontext->current;
|
|
break;
|
|
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_KEY:
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_VALUE:
|
|
result=NULL;
|
|
break;
|
|
|
|
default:
|
|
librdf_log(icontext->iterator->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"Unknown iterator method flag %d", flags);
|
|
result=NULL;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static void
|
|
librdf_storage_list_get_contexts_finished(void* iterator)
|
|
{
|
|
librdf_storage_list_get_contexts_iterator_context* icontext=(librdf_storage_list_get_contexts_iterator_context*)iterator;
|
|
|
|
if(icontext->iterator)
|
|
librdf_free_iterator(icontext->iterator);
|
|
|
|
librdf_free_hash_datum(icontext->key);
|
|
|
|
if(icontext->current)
|
|
librdf_free_node(icontext->current);
|
|
|
|
if(icontext->storage)
|
|
librdf_storage_remove_reference(icontext->storage);
|
|
|
|
LIBRDF_FREE(librdf_storage_list_get_contexts_iterator_context, icontext);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_list_context_get_contexts:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* List all context nodes in a storage.
|
|
*
|
|
* Return value: #librdf_iterator of context_nodes or NULL on failure or no contexts
|
|
**/
|
|
static librdf_iterator*
|
|
librdf_storage_list_get_contexts(librdf_storage* storage)
|
|
{
|
|
librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
|
|
librdf_storage_list_get_contexts_iterator_context* icontext;
|
|
librdf_iterator* iterator;
|
|
|
|
if(!context->index_contexts) {
|
|
librdf_log(storage->world, 0, LIBRDF_LOG_WARN, LIBRDF_FROM_STORAGE, NULL,
|
|
"Storage was created without context support");
|
|
return NULL;
|
|
}
|
|
|
|
icontext=(librdf_storage_list_get_contexts_iterator_context*)LIBRDF_CALLOC(librdf_storage_list_get_contexts_iterator_context, 1, sizeof(librdf_storage_list_get_contexts_iterator_context));
|
|
if(!icontext)
|
|
return NULL;
|
|
|
|
icontext->key=librdf_new_hash_datum(storage->world, NULL, 0);
|
|
if(!icontext->key)
|
|
return NULL;
|
|
|
|
icontext->storage=storage;
|
|
librdf_storage_add_reference(icontext->storage);
|
|
|
|
icontext->iterator=librdf_hash_keys(context->contexts, icontext->key);
|
|
if(!icontext->iterator) {
|
|
librdf_storage_list_get_contexts_finished(icontext);
|
|
return librdf_new_empty_iterator(storage->world);
|
|
}
|
|
|
|
|
|
iterator=librdf_new_iterator(storage->world,
|
|
(void*)icontext,
|
|
&librdf_storage_list_get_contexts_is_end,
|
|
&librdf_storage_list_get_contexts_next_method,
|
|
&librdf_storage_list_get_contexts_get_method,
|
|
&librdf_storage_list_get_contexts_finished);
|
|
if(!iterator)
|
|
librdf_storage_list_get_contexts_finished(icontext);
|
|
return iterator;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* librdf_storage_list_get_feature:
|
|
* @storage: #librdf_storage object
|
|
* @feature: #librdf_uri feature property
|
|
*
|
|
* Get the value of a storage feature.
|
|
*
|
|
* Return value: #librdf_node feature value or NULL if no such feature
|
|
* exists or the value is empty.
|
|
**/
|
|
static librdf_node*
|
|
librdf_storage_list_get_feature(librdf_storage* storage, librdf_uri* feature)
|
|
{
|
|
librdf_storage_list_context* scontext=(librdf_storage_list_context*)storage->context;
|
|
unsigned char *uri_string;
|
|
|
|
if(!feature)
|
|
return NULL;
|
|
|
|
uri_string=librdf_uri_as_string(feature);
|
|
if(!uri_string)
|
|
return NULL;
|
|
|
|
if(!strcmp((const char*)uri_string, LIBRDF_MODEL_FEATURE_CONTEXTS)) {
|
|
unsigned char value[2];
|
|
|
|
sprintf((char*)value, "%d", (scontext->index_contexts != 0));
|
|
return librdf_new_node_from_typed_literal(storage->world,
|
|
value, NULL, NULL);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* local function to register list storage functions */
|
|
|
|
static void
|
|
librdf_storage_list_register_factory(librdf_storage_factory *factory)
|
|
{
|
|
factory->context_length = sizeof(librdf_storage_list_context);
|
|
|
|
factory->init = librdf_storage_list_init;
|
|
factory->terminate = librdf_storage_list_terminate;
|
|
factory->open = librdf_storage_list_open;
|
|
factory->close = librdf_storage_list_close;
|
|
factory->size = librdf_storage_list_size;
|
|
factory->add_statement = librdf_storage_list_add_statement;
|
|
factory->add_statements = librdf_storage_list_add_statements;
|
|
factory->remove_statement = librdf_storage_list_remove_statement;
|
|
factory->contains_statement = librdf_storage_list_contains_statement;
|
|
factory->serialise = librdf_storage_list_serialise;
|
|
factory->find_statements = librdf_storage_list_find_statements;
|
|
factory->context_add_statement = librdf_storage_list_context_add_statement;
|
|
factory->context_remove_statement = librdf_storage_list_context_remove_statement;
|
|
factory->context_serialise = librdf_storage_list_context_serialise;
|
|
factory->get_contexts = librdf_storage_list_get_contexts;
|
|
factory->get_feature = librdf_storage_list_get_feature;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_init_storage_list:
|
|
* @world: world object
|
|
*
|
|
* INTERNAL - initialise the storage_list module.
|
|
**/
|
|
void
|
|
librdf_init_storage_list(librdf_world *world)
|
|
{
|
|
librdf_storage_register_factory(world, "memory", "In memory",
|
|
&librdf_storage_list_register_factory);
|
|
}
|