mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-04 17:49:45 +02:00
970 lines
24 KiB
C
970 lines
24 KiB
C
/* -*- Mode: c; c-basic-offset: 2 -*-
|
|
*
|
|
* rdf_statement.c - RDF Triple (Statement) interface
|
|
*
|
|
* Copyright (C) 2000-2008, David Beckett http://www.dajobe.org/
|
|
* Copyright (C) 2000-2005, 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 <redland.h>
|
|
|
|
|
|
#ifndef STANDALONE
|
|
|
|
/* class methods */
|
|
|
|
/**
|
|
* librdf_init_statement:
|
|
* @world: redland world object
|
|
*
|
|
* INTERNAL - Initialise the statement module.
|
|
*
|
|
**/
|
|
void
|
|
librdf_init_statement(librdf_world *world)
|
|
{
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_finish_statement:
|
|
* @world: redland world object
|
|
*
|
|
* INTERNAL - Terminate the statement module.
|
|
*
|
|
**/
|
|
void
|
|
librdf_finish_statement(librdf_world *world)
|
|
{
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_new_statement:
|
|
* @world: redland world object
|
|
*
|
|
* Constructor - create a new empty #librdf_statement.
|
|
*
|
|
* Return value: a new #librdf_statement or NULL on failure
|
|
**/
|
|
librdf_statement*
|
|
librdf_new_statement(librdf_world *world)
|
|
{
|
|
librdf_statement* new_statement;
|
|
|
|
librdf_world_open(world);
|
|
|
|
new_statement=(librdf_statement*)LIBRDF_CALLOC(librdf_statement, 1,
|
|
sizeof(librdf_statement));
|
|
if(!new_statement)
|
|
return NULL;
|
|
|
|
new_statement->world=world;
|
|
|
|
return new_statement;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_new_statement_from_statement:
|
|
* @statement: #librdf_statement to copy
|
|
*
|
|
* Copy constructor - create a new librdf_statement from an existing librdf_statement.
|
|
*
|
|
* Return value: a new #librdf_statement with copy or NULL on failure
|
|
**/
|
|
librdf_statement*
|
|
librdf_new_statement_from_statement(librdf_statement* statement)
|
|
{
|
|
librdf_statement* new_statement;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
|
|
|
|
if(!statement)
|
|
return NULL;
|
|
|
|
new_statement = librdf_new_statement(statement->world);
|
|
if(!new_statement)
|
|
return NULL;
|
|
|
|
if(statement->subject) {
|
|
new_statement->subject=librdf_new_node_from_node(statement->subject);
|
|
if(!new_statement->subject) {
|
|
librdf_free_statement(new_statement);
|
|
return NULL;
|
|
}
|
|
}
|
|
if(statement->predicate) {
|
|
new_statement->predicate=librdf_new_node_from_node(statement->predicate);
|
|
if(!new_statement->predicate) {
|
|
librdf_free_statement(new_statement);
|
|
return NULL;
|
|
}
|
|
}
|
|
if(statement->object) {
|
|
new_statement->object=librdf_new_node_from_node(statement->object);
|
|
if(!new_statement->object) {
|
|
librdf_free_statement(new_statement);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return new_statement;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_new_statement_from_nodes:
|
|
* @world: redland world object
|
|
* @subject: #librdf_node
|
|
* @predicate: #librdf_node
|
|
* @object: #librdf_node
|
|
*
|
|
* Constructor - create a new #librdf_statement from existing #librdf_node objects.
|
|
*
|
|
* The node objects become owned by the new statement (or freed on error).
|
|
*
|
|
* Return value: a new #librdf_statement with copy or NULL on failure
|
|
**/
|
|
librdf_statement*
|
|
librdf_new_statement_from_nodes(librdf_world *world,
|
|
librdf_node* subject,
|
|
librdf_node* predicate,
|
|
librdf_node* object)
|
|
{
|
|
librdf_statement* new_statement;
|
|
|
|
librdf_world_open(world);
|
|
|
|
new_statement = librdf_new_statement(world);
|
|
if(!new_statement) {
|
|
if(subject)
|
|
librdf_free_node(subject);
|
|
if(predicate)
|
|
librdf_free_node(predicate);
|
|
if(object)
|
|
librdf_free_node(object);
|
|
return NULL;
|
|
}
|
|
|
|
new_statement->subject=subject;
|
|
new_statement->predicate=predicate;
|
|
new_statement->object=object;
|
|
|
|
return new_statement;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_init:
|
|
* @world: redland world object
|
|
* @statement: #librdf_statement object
|
|
*
|
|
* Initialise a statically declared librdf_statement.
|
|
*
|
|
* This MUST be called on a statically declared librdf_statement
|
|
* to initialise it properly. It is the responsibility of the
|
|
* user of the statically allocated librdf_statement to deal
|
|
* with deallocation of any statement parts (subject, predicate, object).
|
|
**/
|
|
void
|
|
librdf_statement_init(librdf_world *world, librdf_statement *statement)
|
|
{
|
|
librdf_world_open(world);
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(statement, librdf_statement);
|
|
|
|
statement->world=world;
|
|
statement->subject=NULL;
|
|
statement->predicate=NULL;
|
|
statement->object=NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_clear:
|
|
* @statement: #librdf_statement object
|
|
*
|
|
* Empty a librdf_statement of nodes.
|
|
*
|
|
**/
|
|
void
|
|
librdf_statement_clear(librdf_statement *statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(statement, librdf_statement);
|
|
|
|
if(statement->subject) {
|
|
librdf_free_node(statement->subject);
|
|
statement->subject=NULL;
|
|
}
|
|
if(statement->predicate) {
|
|
librdf_free_node(statement->predicate);
|
|
statement->predicate=NULL;
|
|
}
|
|
if(statement->object) {
|
|
librdf_free_node(statement->object);
|
|
statement->object=NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_free_statement:
|
|
* @statement: #librdf_statement object
|
|
*
|
|
* Destructor - destroy a #librdf_statement.
|
|
*
|
|
**/
|
|
void
|
|
librdf_free_statement(librdf_statement* statement)
|
|
{
|
|
#ifdef WITH_THREADS
|
|
librdf_world *world;
|
|
#endif
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(statement, librdf_statement);
|
|
|
|
#ifdef WITH_THREADS
|
|
world = statement->world;
|
|
pthread_mutex_lock(world->statements_mutex);
|
|
#endif
|
|
|
|
librdf_statement_clear(statement);
|
|
|
|
#ifdef WITH_THREADS
|
|
pthread_mutex_unlock(world->statements_mutex);
|
|
#endif
|
|
|
|
LIBRDF_FREE(librdf_statement, statement);
|
|
}
|
|
|
|
|
|
|
|
/* methods */
|
|
|
|
/**
|
|
* librdf_statement_get_subject:
|
|
* @statement: #librdf_statement object
|
|
*
|
|
* Get the statement subject.
|
|
*
|
|
* This method returns a SHARED pointer to the subject which must
|
|
* be copied by the caller if needed.
|
|
*
|
|
* Return value: a pointer to the #librdf_node of the statement subject -
|
|
**/
|
|
librdf_node*
|
|
librdf_statement_get_subject(librdf_statement *statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
|
|
|
|
return statement->subject;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_set_subject:
|
|
* @statement: #librdf_statement object
|
|
* @node: #librdf_node of subject
|
|
*
|
|
* Set the statement subject.
|
|
*
|
|
* The subject passed in becomes owned by
|
|
* the statement object and must not be used by the caller after this call.
|
|
**/
|
|
void
|
|
librdf_statement_set_subject(librdf_statement *statement, librdf_node *node)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(statement, librdf_statement);
|
|
|
|
statement->subject=node;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_get_predicate:
|
|
* @statement: #librdf_statement object
|
|
*
|
|
* Get the statement predicate.
|
|
*
|
|
* This method returns a SHARED pointer to the predicate which must
|
|
* be copied by the caller if needed.
|
|
*
|
|
* Return value: a pointer to the #librdf_node of the statement predicate -
|
|
**/
|
|
librdf_node*
|
|
librdf_statement_get_predicate(librdf_statement *statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
|
|
|
|
return statement->predicate;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_set_predicate:
|
|
* @statement: #librdf_statement object
|
|
* @node: #librdf_node of predicate
|
|
*
|
|
* Set the statement predicate.
|
|
*
|
|
* The predicate passed in becomes owned by
|
|
* the statement object and must not be used by the caller after this call.
|
|
**/
|
|
void
|
|
librdf_statement_set_predicate(librdf_statement *statement, librdf_node *node)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(statement, librdf_statement);
|
|
|
|
statement->predicate=node;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_get_object:
|
|
* @statement: #librdf_statement object
|
|
*
|
|
* Get the statement object.
|
|
*
|
|
* This method returns a SHARED pointer to the object which must
|
|
* be copied by the caller if needed.
|
|
*
|
|
* Return value: a pointer to the #librdf_node of the statement object -
|
|
**/
|
|
librdf_node*
|
|
librdf_statement_get_object(librdf_statement *statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
|
|
|
|
return statement->object;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_set_object:
|
|
* @statement: #librdf_statement object
|
|
* @node: #librdf_node of object
|
|
*
|
|
* Set the statement object.
|
|
*
|
|
* The object passed in becomes owned by
|
|
* the statement object and must not be used by the caller after this call.
|
|
**/
|
|
void
|
|
librdf_statement_set_object(librdf_statement *statement, librdf_node *node)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(statement, librdf_statement);
|
|
|
|
statement->object=node;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_is_complete:
|
|
* @statement: #librdf_statement object
|
|
*
|
|
* Check if statement is a complete and legal RDF triple.
|
|
*
|
|
* Checks that all subject, predicate, object fields are present
|
|
* and they have the allowed node types.
|
|
*
|
|
* Return value: non 0 if the statement is complete and legal
|
|
**/
|
|
int
|
|
librdf_statement_is_complete(librdf_statement *statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 0);
|
|
|
|
if(!statement->subject ||
|
|
(!librdf_node_is_resource(statement->subject) &&
|
|
!librdf_node_is_blank(statement->subject)))
|
|
return 0;
|
|
|
|
if(!statement->predicate || !librdf_node_is_resource(statement->predicate))
|
|
return 0;
|
|
|
|
if(!statement->object)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_to_string:
|
|
* @statement: the statement
|
|
*
|
|
* Format the librdf_statement as a string.
|
|
*
|
|
* Formats the statement as a newly allocate string that must be freed by
|
|
* the caller.
|
|
*
|
|
* Return value: the string or NULL on failure.
|
|
**/
|
|
unsigned char *
|
|
librdf_statement_to_string(librdf_statement *statement)
|
|
{
|
|
unsigned char *subject_string, *predicate_string, *object_string;
|
|
unsigned char *s;
|
|
int statement_string_len=0;
|
|
const char *format;
|
|
#define NULL_STRING_LENGTH 6
|
|
static const unsigned char * const null_string=(const unsigned char *)"(null)";
|
|
size_t len;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
|
|
|
|
if(statement->subject) {
|
|
subject_string=librdf_node_to_counted_string(statement->subject, &len);
|
|
if(!subject_string)
|
|
return NULL;
|
|
statement_string_len += len;
|
|
} else {
|
|
subject_string=(unsigned char*)null_string;
|
|
statement_string_len += NULL_STRING_LENGTH;
|
|
}
|
|
|
|
|
|
if(statement->predicate) {
|
|
predicate_string=librdf_node_to_counted_string(statement->predicate, &len);
|
|
if(!predicate_string) {
|
|
if(subject_string != null_string)
|
|
LIBRDF_FREE(cstring, subject_string);
|
|
return NULL;
|
|
}
|
|
statement_string_len += len;
|
|
} else {
|
|
predicate_string=(unsigned char*)null_string;
|
|
statement_string_len += NULL_STRING_LENGTH;
|
|
}
|
|
|
|
|
|
if(statement->object) {
|
|
object_string=librdf_node_to_counted_string(statement->object, &len);
|
|
if(!object_string) {
|
|
if(subject_string != null_string)
|
|
LIBRDF_FREE(cstring, subject_string);
|
|
if(predicate_string != null_string)
|
|
LIBRDF_FREE(cstring, predicate_string);
|
|
return NULL;
|
|
}
|
|
statement_string_len += len;
|
|
} else {
|
|
object_string=(unsigned char*)null_string;
|
|
statement_string_len += NULL_STRING_LENGTH;
|
|
}
|
|
|
|
|
|
|
|
#define LIBRDF_STATEMENT_FORMAT_STRING_LITERAL "{%s, %s, \"%s\"}"
|
|
#define LIBRDF_STATEMENT_FORMAT_RESOURCE_LITERAL "{%s, %s, %s}"
|
|
statement_string_len += + 1 + /* "{" %s */
|
|
2 + /* ", " %s */
|
|
2 + /* ", " %s */
|
|
1; /* "}" */
|
|
if(statement->object &&
|
|
librdf_node_get_type(statement->object) == LIBRDF_NODE_TYPE_LITERAL) {
|
|
format=LIBRDF_STATEMENT_FORMAT_STRING_LITERAL;
|
|
statement_string_len+=2; /* Extra "" around literal */
|
|
} else {
|
|
format=LIBRDF_STATEMENT_FORMAT_RESOURCE_LITERAL;
|
|
}
|
|
|
|
s=(unsigned char*)LIBRDF_MALLOC(cstring, statement_string_len+1);
|
|
if(s)
|
|
sprintf((char*)s, format, subject_string, predicate_string, object_string);
|
|
|
|
/* always free allocated intermediate strings */
|
|
if(subject_string != null_string)
|
|
LIBRDF_FREE(cstring, subject_string);
|
|
if(predicate_string != null_string)
|
|
LIBRDF_FREE(cstring, predicate_string);
|
|
if(object_string != null_string)
|
|
LIBRDF_FREE(cstring, object_string);
|
|
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* librdf_statement_print:
|
|
* @statement: the statement
|
|
* @fh: file handle
|
|
*
|
|
* Pretty print the statement to a file descriptor.
|
|
*
|
|
* This method is for debugging and the format of the output should
|
|
* not be relied on.
|
|
*
|
|
**/
|
|
void
|
|
librdf_statement_print(librdf_statement *statement, FILE *fh)
|
|
{
|
|
unsigned char *s;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(statement, librdf_statement);
|
|
|
|
if(!statement)
|
|
return;
|
|
|
|
s=librdf_statement_to_string(statement);
|
|
if(!s)
|
|
return;
|
|
fputs((const char*)s, fh);
|
|
LIBRDF_FREE(cstring, s);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* librdf_statement_equals:
|
|
* @statement1: first #librdf_statement
|
|
* @statement2: second #librdf_statement
|
|
*
|
|
* Check if two statements are equal.
|
|
*
|
|
* Return value: non 0 if statements are equal
|
|
**/
|
|
int
|
|
librdf_statement_equals(librdf_statement* statement1,
|
|
librdf_statement* statement2)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement1, librdf_statement, 0);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement2, librdf_statement, 0);
|
|
|
|
if(!statement1 || !statement2)
|
|
return 0;
|
|
|
|
if(!librdf_node_equals(statement1->subject, statement2->subject))
|
|
return 0;
|
|
|
|
if(!librdf_node_equals(statement1->predicate, statement2->predicate))
|
|
return 0;
|
|
|
|
if(!librdf_node_equals(statement1->object, statement2->object))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_match:
|
|
* @statement: statement
|
|
* @partial_statement: statement with possible empty parts
|
|
*
|
|
* Match a statement against a 'partial' statement.
|
|
*
|
|
* A partial statement is where some parts of the statement -
|
|
* subject, predicate or object can be empty (NULL).
|
|
* Empty parts match against any value, parts with values
|
|
* must match exactly. Node matching is done via librdf_node_equals()
|
|
*
|
|
* Return value: non 0 on match
|
|
**/
|
|
int
|
|
librdf_statement_match(librdf_statement* statement,
|
|
librdf_statement* partial_statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 0);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(partial_statement, librdf_statement, 0);
|
|
|
|
if(partial_statement->subject &&
|
|
!librdf_node_equals(statement->subject, partial_statement->subject))
|
|
return 0;
|
|
|
|
if(partial_statement->predicate &&
|
|
!librdf_node_equals(statement->predicate, partial_statement->predicate))
|
|
return 0;
|
|
|
|
if(partial_statement->object &&
|
|
!librdf_node_equals(statement->object, partial_statement->object))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_encode:
|
|
* @statement: the statement to serialise
|
|
* @buffer: the buffer to use
|
|
* @length: buffer size
|
|
*
|
|
* Serialise a statement into a buffer.
|
|
*
|
|
* Encodes the given statement in the buffer, which must be of sufficient
|
|
* size. If buffer is NULL, no work is done but the size of buffer
|
|
* required is returned.
|
|
*
|
|
* Return value: the number of bytes written or 0 on failure.
|
|
**/
|
|
size_t
|
|
librdf_statement_encode(librdf_statement* statement,
|
|
unsigned char *buffer,
|
|
size_t length)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 0);
|
|
|
|
return librdf_statement_encode_parts(statement, NULL,
|
|
buffer, length,
|
|
LIBRDF_STATEMENT_ALL);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_encode_parts:
|
|
* @statement: statement to serialise
|
|
* @context_node: #librdf_node context node (can be NULL)
|
|
* @buffer: the buffer to use
|
|
* @length: buffer size
|
|
* @fields: fields to encode
|
|
*
|
|
* Serialise parts of a statement into a buffer.
|
|
*
|
|
* Encodes the given statement in the buffer, which must be of sufficient
|
|
* size. If buffer is NULL, no work is done but the size of buffer
|
|
* required is returned.
|
|
*
|
|
* The fields values are or-ed combinations of:
|
|
* LIBRDF_STATEMENT_SUBJECT LIBRDF_STATEMENT_PREDICATE
|
|
* LIBRDF_STATEMENT_OBJECT
|
|
* or LIBRDF_STATEMENT_ALL for subject,prdicate,object fields
|
|
*
|
|
* If context_node is given, it is encoded also
|
|
*
|
|
* Return value: the number of bytes written or 0 on failure.
|
|
**/
|
|
size_t
|
|
librdf_statement_encode_parts(librdf_statement* statement,
|
|
librdf_node* context_node,
|
|
unsigned char *buffer, size_t length,
|
|
librdf_statement_part fields)
|
|
{
|
|
size_t total_length=0;
|
|
size_t node_len;
|
|
unsigned char *p;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 0);
|
|
|
|
/* min size */
|
|
if(buffer && length < 1)
|
|
return 0;
|
|
|
|
p=buffer;
|
|
/* magic number 'x' */
|
|
if(p) {
|
|
*p++='x';
|
|
length--;
|
|
}
|
|
total_length++;
|
|
|
|
if((fields & LIBRDF_STATEMENT_SUBJECT) && statement->subject) {
|
|
/* 's' + subject */
|
|
if(p) {
|
|
*p++='s';
|
|
length--;
|
|
}
|
|
total_length++;
|
|
|
|
node_len=librdf_node_encode(statement->subject, p, length);
|
|
if(!node_len)
|
|
return 0;
|
|
if(p) {
|
|
p += node_len;
|
|
length -= node_len;
|
|
}
|
|
|
|
|
|
total_length += node_len;
|
|
}
|
|
|
|
|
|
if((fields & LIBRDF_STATEMENT_PREDICATE) && statement->predicate) {
|
|
/* 'p' + predicate */
|
|
if(p) {
|
|
*p++='p';
|
|
length--;
|
|
}
|
|
total_length++;
|
|
|
|
node_len=librdf_node_encode(statement->predicate, p, length);
|
|
if(!node_len)
|
|
return 0;
|
|
if(p) {
|
|
p += node_len;
|
|
length -= node_len;
|
|
}
|
|
|
|
total_length += node_len;
|
|
}
|
|
|
|
if((fields & LIBRDF_STATEMENT_OBJECT) && statement->object) {
|
|
/* 'o' object */
|
|
if(p) {
|
|
*p++='o';
|
|
length--;
|
|
}
|
|
total_length++;
|
|
|
|
node_len= librdf_node_encode(statement->object, p, length);
|
|
if(!node_len)
|
|
return 0;
|
|
if(p) {
|
|
p += node_len;
|
|
length -= node_len;
|
|
}
|
|
|
|
total_length += node_len;
|
|
}
|
|
|
|
if(context_node) {
|
|
/* 'o' object */
|
|
if(p) {
|
|
*p++='c';
|
|
length--;
|
|
}
|
|
total_length++;
|
|
|
|
node_len= librdf_node_encode(context_node, p, length);
|
|
if(!node_len)
|
|
return 0;
|
|
if(p) {
|
|
p += node_len;
|
|
length -= node_len;
|
|
}
|
|
|
|
total_length += node_len;
|
|
}
|
|
|
|
return total_length;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_decode:
|
|
* @statement: the statement to deserialise into
|
|
* @buffer: the buffer to use
|
|
* @length: buffer size
|
|
*
|
|
* Decodes a statement from a buffer.
|
|
*
|
|
* Decodes the serialised statement (as created by librdf_statement_encode() )
|
|
* from the given buffer.
|
|
*
|
|
* Return value: number of bytes used or 0 on failure (bad encoding, allocation failure)
|
|
**/
|
|
size_t
|
|
librdf_statement_decode(librdf_statement* statement,
|
|
unsigned char *buffer, size_t length)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 0);
|
|
|
|
return librdf_statement_decode_parts(statement, NULL, buffer, length);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_statement_decode_parts:
|
|
* @statement: the statement to deserialise into
|
|
* @context_node: pointer to #librdf_node context_node to deserialise into
|
|
* @buffer: the buffer to use
|
|
* @length: buffer size
|
|
*
|
|
* Decodes a statement + context node from a buffer.
|
|
*
|
|
* Decodes the serialised statement (as created by librdf_statement_encode() )
|
|
* from the given buffer. If a context node is found and context_node is
|
|
* not NULL, a pointer to the new #librdf_node is stored in *context_node.
|
|
*
|
|
* Return value: number of bytes used or 0 on failure (bad encoding, allocation failure)
|
|
**/
|
|
size_t
|
|
librdf_statement_decode_parts(librdf_statement* statement,
|
|
librdf_node** context_node,
|
|
unsigned char *buffer, size_t length)
|
|
{
|
|
unsigned char *p;
|
|
librdf_node* node;
|
|
unsigned char type;
|
|
size_t total_length=0;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 0);
|
|
|
|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
|
|
LIBRDF_DEBUG2("Decoding buffer of %d bytes\n", length);
|
|
#endif
|
|
|
|
|
|
/* absolute minimum - first byte is type */
|
|
if(length < 1)
|
|
return 0;
|
|
|
|
p=buffer;
|
|
if(*p++ != 'x')
|
|
return 0;
|
|
length--;
|
|
total_length++;
|
|
|
|
|
|
while(length>0) {
|
|
size_t node_len;
|
|
|
|
type=*p++;
|
|
length--;
|
|
total_length++;
|
|
|
|
if(!length)
|
|
return 0;
|
|
|
|
if(!(node=librdf_node_decode(statement->world, &node_len, p, length)))
|
|
return 0;
|
|
|
|
p += node_len;
|
|
length -= node_len;
|
|
total_length += node_len;
|
|
|
|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
|
|
LIBRDF_DEBUG3("Found type %c (%d bytes)\n", type, node_len);
|
|
#endif
|
|
|
|
switch(type) {
|
|
case 's': /* subject */
|
|
statement->subject=node;
|
|
break;
|
|
|
|
case 'p': /* predicate */
|
|
statement->predicate=node;
|
|
break;
|
|
|
|
case 'o': /* object */
|
|
statement->object=node;
|
|
break;
|
|
|
|
case 'c': /* context */
|
|
if(context_node)
|
|
*context_node=node;
|
|
else
|
|
librdf_free_node(node);
|
|
break;
|
|
|
|
default:
|
|
librdf_log(statement->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STATEMENT, NULL,
|
|
"Illegal statement encoding '%c' seen", p[-1]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return total_length;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/* TEST CODE */
|
|
|
|
|
|
#ifdef STANDALONE
|
|
|
|
/* one more prototype */
|
|
int main(int argc, char *argv[]);
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
librdf_statement *statement, *statement2;
|
|
int size, size2;
|
|
const char *program=librdf_basename((const char*)argv[0]);
|
|
char *s, *buffer;
|
|
librdf_world *world;
|
|
|
|
world=librdf_new_world();
|
|
librdf_world_open(world);
|
|
|
|
fprintf(stderr, "%s: Creating statement\n", program);
|
|
statement=librdf_new_statement(world);
|
|
|
|
s=(char*)librdf_statement_to_string(statement);
|
|
fprintf(stderr, "%s: Empty statement: %s\n", program, s);
|
|
LIBRDF_FREE(cstring, s);
|
|
|
|
librdf_statement_set_subject(statement, librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/net/dajobe/"));
|
|
librdf_statement_set_predicate(statement, librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/dc/elements/1.1/#Creator"));
|
|
librdf_statement_set_object(statement, librdf_new_node_from_literal(world, (const unsigned char*)"Dave Beckett", NULL, 0));
|
|
|
|
s=(char*)librdf_statement_to_string(statement);
|
|
fprintf(stderr, "%s: Resulting statement: %s\n", program, s);
|
|
LIBRDF_FREE(cstring, s);
|
|
|
|
size=librdf_statement_encode(statement, NULL, 0);
|
|
fprintf(stdout, "%s: Encoding statement requires %d bytes\n", program, size);
|
|
buffer=(char*)LIBRDF_MALLOC(cstring, size);
|
|
|
|
fprintf(stdout, "%s: Encoding statement in buffer\n", program);
|
|
size2=librdf_statement_encode(statement, (unsigned char*)buffer, size);
|
|
if(size2 != size) {
|
|
fprintf(stderr, "%s: Encoding statement used %d bytes, expected it to use %d\n", program, size2, size);
|
|
return(1);
|
|
}
|
|
|
|
|
|
fprintf(stdout, "%s: Creating new statement\n", program);
|
|
statement2=librdf_new_statement(world);
|
|
|
|
fprintf(stdout, "%s: Decoding statement from buffer\n", program);
|
|
if(!librdf_statement_decode(statement2, (unsigned char*)buffer, size)) {
|
|
fprintf(stderr, "%s: Decoding statement failed\n", program);
|
|
return(1);
|
|
}
|
|
LIBRDF_FREE(cstring, buffer);
|
|
|
|
fprintf(stdout, "%s: New statement is: ", program);
|
|
librdf_statement_print(statement2, stdout);
|
|
fputs("\n", stdout);
|
|
|
|
|
|
fprintf(stdout, "%s: Freeing statements\n", program);
|
|
librdf_free_statement(statement2);
|
|
librdf_free_statement(statement);
|
|
|
|
|
|
librdf_free_world(world);
|
|
|
|
/* keep gcc -Wall happy */
|
|
return(0);
|
|
}
|
|
|
|
#endif
|