1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-02 16:49:41 +02:00
2010-01-24 09:19:39 +00:00

2044 lines
57 KiB
C

/* -*- Mode: c; c-basic-offset: 2 -*-
*
* rdf_node.c - RDF Node (RDF URI, Literal, Blank Node) 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>
/* needed for utf8 functions and definition of 'byte' */
#include <rdf_utf8.h>
#ifndef STANDALONE
/* hashes - resource, literal, blank */
enum {
H_RESOURCE,
H_LITERAL,
H_BLANK,
H_LAST=H_BLANK
};
#define H_COUNT (H_LAST+1)
/* class functions */
/**
* librdf_init_node:
* @world: redland world object
*
* INTERNAL - Initialise the node module.
*
**/
void
librdf_init_node(librdf_world* world)
{
int i;
for(i=0; i<H_COUNT; i++) {
world->nodes_hash[i]=librdf_new_hash(world, NULL);
if(!world->nodes_hash[i])
LIBRDF_FATAL1(world, LIBRDF_FROM_NODE, "Failed to create Nodes hash from factory");
if(librdf_hash_open(world->nodes_hash[i], NULL, 0, 1, 1, NULL))
LIBRDF_FATAL1(world, LIBRDF_FROM_NODE, "Failed to open Nodes hash");
}
}
/**
* librdf_finish_node:
* @world: redland world object
*
* INTERNAL - Terminate the node module.
*
**/
void
librdf_finish_node(librdf_world *world)
{
int i;
for(i=0; i<H_COUNT; i++) {
if(world->nodes_hash[i]) {
librdf_hash_close(world->nodes_hash[i]);
librdf_free_hash(world->nodes_hash[i]);
}
}
}
/* constructors */
/**
* librdf_new_node:
* @world: redland world object
*
* Constructor - create a new #librdf_node object with a private identifier.
*
* Calls librdf_new_node_from_blank_identifier(world, NULL) to
* construct a new redland blank node identifier and make a
* new librdf_node object for it.
*
* Return value: a new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node(librdf_world *world)
{
librdf_world_open(world);
return librdf_new_node_from_blank_identifier(world, (unsigned char*)NULL);
}
/**
* librdf_new_node_from_uri_string_or_uri:
* @world: redland world object
* @uri_string: string representing a URI
* @uri: #librdf_uri object
*
* INTERNAL Constructor - create a new #librdf_node object from a URI string or URI object.
*
* Return value: a new #librdf_node object or NULL on failure
**/
static librdf_node*
librdf_new_node_from_uri_string_or_uri(librdf_world *world,
const unsigned char *uri_string,
librdf_uri *uri)
{
librdf_node* new_node;
librdf_uri *new_uri;
librdf_hash_datum key, value; /* on stack - not allocated */
librdf_hash_datum *old_value;
librdf_world_open(world);
LIBRDF_ASSERT_RETURN((uri_string == NULL && uri == NULL),
"both uri_string and uri are NULL", NULL);
if(!uri_string && !uri)
return NULL;
if(uri_string && uri) {
LIBRDF_DEBUG3("Called with both a URI string %s and object URI %s\n", uri_string, librdf_uri_as_string(uri));
return NULL;
}
if(uri_string) {
new_uri=librdf_new_uri(world, uri_string);
if(!new_uri)
return NULL;
} else
new_uri=librdf_new_uri_from_uri(uri);
#ifdef WITH_THREADS
pthread_mutex_lock(world->nodes_mutex);
#endif
key.data=&new_uri;
key.size=sizeof(librdf_uri*);
/* if the existing node found in resource hash, return it */
if((old_value=librdf_hash_get_one(world->nodes_hash[H_RESOURCE], &key))) {
new_node=*(librdf_node**)old_value->data;
librdf_free_uri(new_uri);
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
LIBRDF_DEBUG3("Found existing resource node with URI %s in hash with current usage %d\n", uri_string, new_node->usage);
#endif
librdf_free_hash_datum(old_value);
new_node->usage++;
goto unlock;
}
/* otherwise create a new one */
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
LIBRDF_DEBUG2("Creating new resource node with URI %s in hash\n", uri_string);
#endif
new_node = (librdf_node*)LIBRDF_CALLOC(librdf_node, 1, sizeof(librdf_node));
if(!new_node) {
librdf_free_uri(new_uri);
goto unlock;
}
new_node->world=world;
new_node->value.resource.uri=new_uri;
new_node->type = LIBRDF_NODE_TYPE_RESOURCE;
new_node->usage=1;
value.data=&new_node; value.size=sizeof(librdf_node*);
/* store in hash: (librdf_uri*)uri => (librdf_node*) */
if(librdf_hash_put(world->nodes_hash[H_RESOURCE], &key, &value)) {
LIBRDF_FREE(librdf_node, new_node);
librdf_free_uri(new_uri);
new_node=NULL;
}
unlock:
#ifdef WITH_THREADS
pthread_mutex_unlock(world->nodes_mutex);
#endif
return new_node;
}
/**
* librdf_new_node_from_uri_string:
* @world: redland world object
* @uri_string: string representing a URI
*
* Constructor - create a new #librdf_node object from a URI string.
*
* Return value: a new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_uri_string(librdf_world *world,
const unsigned char *uri_string)
{
librdf_world_open(world);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(uri_string, string, NULL);
return librdf_new_node_from_uri_string_or_uri(world, uri_string, NULL);
}
/* Create a new (Resource) Node and set the URI. */
/**
* librdf_new_node_from_uri:
* @world: redland world object
* @uri: #librdf_uri object
*
* Constructor - create a new resource #librdf_node object with a given URI.
*
* Return value: a new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_uri(librdf_world *world, librdf_uri *uri)
{
librdf_world_open(world);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(uri, librdf_uri, NULL);
return librdf_new_node_from_uri_string_or_uri(world, NULL, uri);
}
/**
* librdf_new_node_from_uri_local_name:
* @world: redland world object
* @uri: #librdf_uri object
* @local_name: local name to append to URI
*
* Constructor - create a new resource #librdf_node object with a given URI and local name.
*
* Return value: a new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_uri_local_name(librdf_world *world,
librdf_uri *uri,
const unsigned char *local_name)
{
librdf_uri *new_uri;
librdf_node* new_node;
librdf_world_open(world);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(uri, librdf_uri, NULL);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(local_name, string, NULL);
new_uri=librdf_new_uri_from_uri_local_name(uri, local_name);
if(!new_uri)
return NULL;
new_node=librdf_new_node_from_uri_string_or_uri(world, NULL, new_uri);
librdf_free_uri(new_uri);
return new_node;
}
/**
* librdf_new_node_from_normalised_uri_string:
* @world: redland world object
* @uri_string: string representing a URI
* @source_uri: source URI
* @base_uri: base URI
*
* Constructor - create a new #librdf_node object from a URI string normalised to a new base URI.
*
* Return value: a new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_normalised_uri_string(librdf_world *world,
const unsigned char *uri_string,
librdf_uri *source_uri,
librdf_uri *base_uri)
{
librdf_uri* new_uri;
librdf_node* new_node;
librdf_world_open(world);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(uri_string, string, NULL);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(source_uri, librdf_uri, NULL);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(base_uri, librdf_uri, NULL);
new_uri=librdf_new_uri_normalised_to_base(uri_string, source_uri, base_uri);
if(!new_uri)
return NULL;
new_node=librdf_new_node_from_uri_string_or_uri(world, NULL, new_uri);
librdf_free_uri(new_uri);
return new_node;
}
/**
* librdf_new_node_from_literal:
* @world: redland world object
* @string: literal string value
* @xml_language: literal XML language (or NULL, empty string)
* @is_wf_xml: non 0 if literal is XML
*
* Constructor - create a new literal #librdf_node object.
*
* 0.9.12: xml_space argument deleted
*
* An @xml_language cannot be used when @is_wf_xml is non-0. If both
* are given, NULL is returned. If @xml_language is the empty string,
* it is the equivalent to NULL.
*
* Return value: new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_literal(librdf_world *world,
const unsigned char *string,
const char *xml_language,
int is_wf_xml)
{
size_t xml_language_len=0;
librdf_world_open(world);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(string, string, NULL);
if(xml_language && !*xml_language)
xml_language=NULL;
if(xml_language) {
if(is_wf_xml)
return NULL;
xml_language_len=strlen(xml_language);
}
return librdf_new_node_from_typed_counted_literal(world,
string,
strlen((const char*)string),
xml_language,
xml_language_len,
(is_wf_xml ?
LIBRDF_RS_XMLLiteral_URI(world) : NULL)
);
}
/**
* librdf_new_node_from_typed_counted_literal:
* @world: redland world object
* @value: literal string value
* @value_len: literal string value length
* @xml_language: literal XML language (or NULL, empty string)
* @xml_language_len: literal XML language length (not used if @xml_language is NULL)
* @datatype_uri: URI of typed literal datatype or NULL
*
* Constructor - create a new typed literal #librdf_node object.
*
* Only one of @xml_language or @datatype_uri may be given. If both
* are given, NULL is returned. If @xml_language is the empty string,
* it is the equivalent to NULL.
*
* Return value: new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_typed_counted_literal(librdf_world *world,
const unsigned char *value,
size_t value_len,
const char *xml_language,
size_t xml_language_len,
librdf_uri* datatype_uri)
{
librdf_node* new_node;
unsigned char *new_value;
char *new_xml_language;
librdf_hash_datum key, value_hd; /* on stack - not allocated */
librdf_hash_datum *old_value;
size_t size;
unsigned char *buffer;
librdf_world_open(world);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(value, string, NULL);
if(xml_language && !*xml_language)
xml_language=NULL;
if(xml_language && datatype_uri)
return NULL;
#ifdef WITH_THREADS
pthread_mutex_lock(world->nodes_mutex);
#endif
new_node = (librdf_node*)LIBRDF_CALLOC(librdf_node, 1, sizeof(librdf_node));
if(!new_node)
goto unlock;
new_node->world=world;
/* set type */
new_node->type=LIBRDF_NODE_TYPE_LITERAL;
/* the only time the string literal length should ever be measured */
new_node->value.literal.string_len = value_len;
new_value=(unsigned char*)LIBRDF_MALLOC(cstring, value_len + 1);
if(!new_value) {
LIBRDF_FREE(librdf_node, new_node);
new_node=NULL;
goto unlock;
}
strncpy((char*)new_value, (const char*)value, value_len);
new_value[value_len]='\0';
new_node->value.literal.string=new_value;
if(xml_language && *xml_language) {
new_xml_language=(char*)LIBRDF_MALLOC(cstring, xml_language_len + 1);
if(!new_xml_language) {
LIBRDF_FREE(cstring, new_value);
LIBRDF_FREE(librdf_node, new_node);
new_node=NULL;
goto unlock;
}
strncpy(new_xml_language, xml_language, xml_language_len);
new_xml_language[xml_language_len]='\0';
new_node->value.literal.xml_language=new_xml_language;
new_node->value.literal.xml_language_len=xml_language_len;
} else
new_xml_language=NULL;
if(datatype_uri) {
datatype_uri=librdf_new_uri_from_uri(datatype_uri);
new_node->value.literal.datatype_uri=datatype_uri;
}
size=librdf_node_encode(new_node, NULL, 0);
if(size)
buffer=(unsigned char*)LIBRDF_MALLOC(cstring, size);
else
buffer=NULL;
if(!buffer) {
if(new_xml_language)
LIBRDF_FREE(cstring, new_xml_language);
if(datatype_uri)
librdf_free_uri(datatype_uri);
LIBRDF_FREE(cstring, new_value);
LIBRDF_FREE(librdf_node, new_node);
return NULL;
}
new_node->value.literal.size=size;
new_node->value.literal.key=buffer;
librdf_node_encode(new_node, buffer, size);
key.data=buffer;
key.size=size;
/* if the existing node found in resource hash, return it */
if((old_value=librdf_hash_get_one(world->nodes_hash[H_LITERAL], &key))) {
LIBRDF_FREE(cstring, buffer);
if(new_xml_language)
LIBRDF_FREE(cstring, new_xml_language);
if(datatype_uri)
librdf_free_uri(datatype_uri);
LIBRDF_FREE(cstring, new_value);
LIBRDF_FREE(librdf_node, new_node);
new_node=*(librdf_node**)old_value->data;
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
LIBRDF_DEBUG3("Found existing resource node with typed literal %s in hash with current usage %d\n", value, new_node->usage);
#endif
librdf_free_hash_datum(old_value);
new_node->usage++;
goto unlock;
}
/* otherwise add the new node */
new_node->usage=1;
value_hd.data=&new_node; value_hd.size=sizeof(librdf_node*);
/* store in hash: (serialised node) => (librdf_node*) */
if(librdf_hash_put(world->nodes_hash[H_LITERAL], &key, &value_hd)) {
LIBRDF_FREE(cstring, buffer);
if(new_xml_language)
LIBRDF_FREE(cstring, new_xml_language);
if(datatype_uri)
librdf_free_uri(datatype_uri);
LIBRDF_FREE(cstring, new_value);
LIBRDF_FREE(librdf_node, new_node);
new_node=NULL;
}
unlock:
#ifdef WITH_THREADS
pthread_mutex_unlock(world->nodes_mutex);
#endif
return new_node;
}
/**
* librdf_new_node_from_typed_literal:
* @world: redland world object
* @value: literal string value
* @xml_language: literal XML language (or NULL, empty string)
* @datatype_uri: URI of typed literal datatype or NULL
*
* Constructor - create a new typed literal #librdf_node object.
*
* Only one of @xml_language or @datatype_uri may be given. If both
* are given, NULL is returned. If @xml_language is the empty string,
* it is the equivalent to NULL.
*
* Return value: new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_typed_literal(librdf_world *world,
const unsigned char *value,
const char *xml_language,
librdf_uri* datatype_uri)
{
size_t xml_language_len=0;
librdf_world_open(world);
if(xml_language)
xml_language_len=strlen(xml_language);
return librdf_new_node_from_typed_counted_literal(world, value,
strlen((const char*)value),
xml_language,
xml_language_len,
datatype_uri);
}
/**
* librdf_new_node_from_blank_identifier:
* @world: redland world object
* @identifier: blank node identifier or NULL
*
* Constructor - create a new blank node #librdf_node object from a blank node identifier.
*
* If no identifier string is given, creates a new internal identifier
* and assigns it.
*
* Return value: new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_blank_identifier(librdf_world *world,
const unsigned char *identifier)
{
librdf_node* new_node;
unsigned char *new_identifier;
int len;
librdf_hash_datum key, value; /* on stack - not allocated */
librdf_hash_datum *old_value;
librdf_world_open(world);
#ifdef WITH_THREADS
pthread_mutex_lock(world->nodes_mutex);
#endif
if(!identifier) {
new_identifier=librdf_world_get_genid(world);
if(!new_identifier) {
new_node=NULL;
goto unlock;
}
len=strlen((const char *)new_identifier);
} else {
len=strlen((const char*)identifier);
new_identifier=(unsigned char*)LIBRDF_MALLOC(cstring, len+1);
if(!new_identifier) {
new_node=NULL;
goto unlock;
}
strcpy((char*)new_identifier, (const char*)identifier);
}
key.data=new_identifier;
key.size=len;
/* if the existing node found in resource hash, return it */
if((old_value=librdf_hash_get_one(world->nodes_hash[H_BLANK], &key))) {
new_node=*(librdf_node**)old_value->data;
LIBRDF_FREE(cstring, new_identifier);
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
LIBRDF_DEBUG3("Found existing blank node identifier %s in hash with current usage %d\n", new_identifier, new_node->usage);
#endif
librdf_free_hash_datum(old_value);
new_node->usage++;
goto unlock;
}
new_node = (librdf_node*)LIBRDF_CALLOC(librdf_node, 1, sizeof(librdf_node));
if(!new_node) {
LIBRDF_FREE(cstring, new_identifier);
goto unlock;
}
new_node->world=world;
new_node->value.blank.identifier=new_identifier;
new_node->value.blank.identifier_len=len;
new_node->type=LIBRDF_NODE_TYPE_BLANK;
new_node->usage=1;
value.data=&new_node; value.size=sizeof(librdf_node*);
/* store in hash: (blank node ID string) => (librdf_node*) */
if(librdf_hash_put(world->nodes_hash[H_BLANK], &key, &value)) {
LIBRDF_FREE(librdf_node, new_node);
LIBRDF_FREE(cstring, new_identifier);
new_node=NULL;
}
unlock:
#ifdef WITH_THREADS
pthread_mutex_unlock(world->nodes_mutex);
#endif
return new_node;
}
/**
* librdf_new_node_from_node:
* @node: #librdf_node object to copy
*
* Copy constructor - create a new librdf_node object from an existing librdf_node object.
*
* Return value: a new #librdf_node object or NULL on failure
**/
librdf_node*
librdf_new_node_from_node(librdf_node *node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
node->usage++;
return node;
}
/**
* librdf_free_node:
* @node: #librdf_node object
*
* Destructor - destroy an #librdf_node object.
*
**/
void
librdf_free_node(librdf_node *node)
{
librdf_hash_datum key; /* on stack */
#ifdef WITH_THREADS
librdf_world *world;
#endif
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(node, librdf_node);
#ifdef WITH_THREADS
world = node->world;
pthread_mutex_lock(world->nodes_mutex);
#endif
node->usage--;
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
LIBRDF_DEBUG3("Node %p usage count now %d\n", node, node->usage);
#endif
/* decrement usage, don't free if not 0 yet*/
if(node->usage) {
#ifdef WITH_THREADS
pthread_mutex_unlock(world->nodes_mutex);
#endif
return;
}
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
LIBRDF_DEBUG2("Deleting Node %p from hash\n", node);
#endif
switch(node->type) {
case LIBRDF_NODE_TYPE_RESOURCE:
key.data=&node->value.resource.uri;
key.size=sizeof(librdf_uri*);
/* Hash deletion fails only if the key is not found.
This is not a fatal error so do not check for return value. */
librdf_hash_delete_all(node->world->nodes_hash[H_RESOURCE], &key);
librdf_free_uri(node->value.resource.uri);
break;
case LIBRDF_NODE_TYPE_LITERAL:
if(node->value.literal.key) {
key.data=node->value.literal.key;
key.size=node->value.literal.size;
librdf_hash_delete_all(node->world->nodes_hash[H_LITERAL], &key); /* see above */
LIBRDF_FREE(cstring, node->value.literal.key);
}
if(node->value.literal.string != NULL)
LIBRDF_FREE(cstring, node->value.literal.string);
if(node->value.literal.xml_language != NULL)
LIBRDF_FREE(cstring, node->value.literal.xml_language);
if(node->value.literal.datatype_uri != NULL)
librdf_free_uri(node->value.literal.datatype_uri);
break;
case LIBRDF_NODE_TYPE_BLANK:
key.data=node->value.blank.identifier;
key.size=node->value.blank.identifier_len;
librdf_hash_delete_all(node->world->nodes_hash[H_BLANK], &key); /* see above */
if(node->value.blank.identifier != NULL)
LIBRDF_FREE(cstring, node->value.blank.identifier);
break;
case LIBRDF_NODE_TYPE_UNKNOWN:
default:
break;
}
#ifdef WITH_THREADS
pthread_mutex_unlock(world->nodes_mutex);
#endif
LIBRDF_FREE(librdf_node, node);
}
/* functions / methods */
/**
* librdf_node_get_uri:
* @node: the node object
*
* Get the URI for a node object.
*
* Returns a pointer to the URI object held by the node, it must be
* copied if it is wanted to be used by the caller.
*
* Return value: URI object or NULL if node has no URI.
**/
librdf_uri*
librdf_node_get_uri(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
if(node->type != LIBRDF_NODE_TYPE_RESOURCE)
return NULL;
return node->value.resource.uri;
}
/**
* librdf_node_get_type:
* @node: the node object
*
* Get the type of the node.
*
* Return value: the node type
**/
librdf_node_type
librdf_node_get_type(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, LIBRDF_NODE_TYPE_UNKNOWN);
return node->type;
}
#ifdef LIBRDF_DEBUG
/* FIXME: For debugging purposes only */
static const char* const librdf_node_type_names[] =
{"Unknown", "Resource", "Literal", "<Unused1>", "Blank"};
/*
* librdf_node_get_type_as_string - Get a string representation for the type of the node
* @type: the node type
*
* The type is that returned by the librdf_node_get_type method
*
* Return value: a pointer to a shared copy of the string or NULL if unknown.
**/
const char*
librdf_node_get_type_as_string(int type)
{
if(type < 0 || type > LIBRDF_NODE_TYPE_LAST)
return NULL;
return librdf_node_type_names[type];
}
#endif
/**
* librdf_node_get_literal_value:
* @node: the node object
*
* Get the string literal value of the node.
*
* Returns a pointer to the literal value held by the node, it must be
* copied if it is wanted to be used by the caller.
*
* Return value: the literal string or NULL if node is not a literal
**/
unsigned char*
librdf_node_get_literal_value(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
if(node->type != LIBRDF_NODE_TYPE_LITERAL)
return NULL;
return node->value.literal.string;
}
/**
* librdf_node_get_literal_value_as_counted_string:
* @node: the node object
* @len_p: pointer to location to store length (or NULL)
*
* Get the string literal value of the node as a counted string.
*
* Returns a pointer to the literal value held by the node, it must be
* copied if it is wanted to be used by the caller.
*
* Return value: the literal string or NULL if node is not a literal
**/
unsigned char*
librdf_node_get_literal_value_as_counted_string(librdf_node* node,
size_t *len_p)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
LIBRDF_ASSERT_RETURN((node->type != LIBRDF_NODE_TYPE_LITERAL),
"node is not type literal", NULL);
if(node->type != LIBRDF_NODE_TYPE_LITERAL)
return NULL;
if(len_p)
*len_p=node->value.literal.string_len;
return node->value.literal.string;
}
/**
* librdf_node_get_literal_value_as_latin1:
* @node: the node object
*
* Get the string literal value of the node as ISO Latin-1.
*
* Returns a newly allocated string containing the conversion of the
* UTF-8 literal value held by the node.
*
* Return value: the literal string or NULL if node is not a literal
**/
char*
librdf_node_get_literal_value_as_latin1(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
LIBRDF_ASSERT_RETURN((node->type != LIBRDF_NODE_TYPE_LITERAL),
"node is not type literal", NULL);
if(node->type != LIBRDF_NODE_TYPE_LITERAL)
return NULL;
return (char*)librdf_utf8_to_latin1((const byte*)node->value.literal.string,
node->value.literal.string_len, NULL);
}
/**
* librdf_node_get_literal_value_language:
* @node: the node object
*
* Get the XML language of the node.
*
* Returns a pointer to the literal language value held by the node, it must
* be copied if it is wanted to be used by the caller.
*
* Return value: the XML language string or NULL if node is not a literal
* or there is no XML language defined.
**/
char*
librdf_node_get_literal_value_language(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
LIBRDF_ASSERT_RETURN((node->type != LIBRDF_NODE_TYPE_LITERAL),
"node is not type literal", NULL);
if(node->type != LIBRDF_NODE_TYPE_LITERAL)
return NULL;
return node->value.literal.xml_language;
}
/**
* librdf_node_get_literal_value_is_wf_xml:
* @node: the node object
*
* Get the XML well-formness property of the node.
*
* Return value: 0 if the XML literal is NOT well formed XML content, or the node is not a literal
**/
int
librdf_node_get_literal_value_is_wf_xml(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
LIBRDF_ASSERT_RETURN((node->type != LIBRDF_NODE_TYPE_LITERAL),
"node is not type literal", 0);
if(node->type != LIBRDF_NODE_TYPE_LITERAL)
return 0;
if(!node->value.literal.datatype_uri)
return 0;
return librdf_uri_equals(node->value.literal.datatype_uri,
LIBRDF_RS_XMLLiteral_URI(node->world));
}
/**
* librdf_node_get_literal_value_datatype_uri:
* @node: the node object
*
* Get the typed literal datatype URI of the literal node.
*
* Return value: shared URI of the datatyped literal or NULL if the node is not a literal, or has no datatype URI
**/
librdf_uri*
librdf_node_get_literal_value_datatype_uri(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
LIBRDF_ASSERT_RETURN((node->type != LIBRDF_NODE_TYPE_LITERAL),
"node is not type literal", NULL);
if(node->type != LIBRDF_NODE_TYPE_LITERAL)
return NULL;
return node->value.literal.datatype_uri;
}
/**
* librdf_node_get_li_ordinal:
* @node: the node object
*
* Get the node li object ordinal value.
*
* Return value: the li ordinal value or < 1 on failure
**/
int
librdf_node_get_li_ordinal(librdf_node* node) {
unsigned char *uri_string;
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
LIBRDF_ASSERT_RETURN((node->type != LIBRDF_NODE_TYPE_RESOURCE),
"node is not type resource", 0);
if(node->type != LIBRDF_NODE_TYPE_RESOURCE)
return -1;
uri_string=librdf_uri_as_string(node->value.resource.uri);
if(strncmp((const char*)uri_string,
(const char*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#_", 44))
return -1;
return atoi((const char*)uri_string+44);
}
/**
* librdf_node_get_blank_identifier:
* @node: the node object
*
* Get the blank node identifier.
*
* Return value: the identifier value
**/
unsigned char *
librdf_node_get_blank_identifier(librdf_node* node) {
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
LIBRDF_ASSERT_RETURN((node->type != LIBRDF_NODE_TYPE_BLANK),
"node is not type blank", NULL);
return node->value.blank.identifier;
}
/**
* librdf_node_is_resource:
* @node: the node object
*
* Check node is a resource.
*
* Return value: non-zero if the node is a resource (URI)
**/
int
librdf_node_is_resource(librdf_node* node) {
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
return (node->type == LIBRDF_NODE_TYPE_RESOURCE);
}
/**
* librdf_node_is_literal:
* @node: the node object
*
* Check node is a literal.
*
* Return value: non-zero if the node is a literal
**/
int
librdf_node_is_literal(librdf_node* node) {
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
return (node->type == LIBRDF_NODE_TYPE_LITERAL);
}
/**
* librdf_node_is_blank:
* @node: the node object
*
* Check node is a blank nodeID.
*
* Return value: non-zero if the node is a blank nodeID
**/
int
librdf_node_is_blank(librdf_node* node) {
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
return (node->type == LIBRDF_NODE_TYPE_BLANK);
}
/**
* librdf_node_to_string:
* @node: the node object
*
* Format the node as a string.
*
* Note a new string is allocated which must be freed by the caller.
*
* Return value: a string value representing the node or NULL on failure
**/
unsigned char*
librdf_node_to_string(librdf_node* node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
return librdf_node_to_counted_string(node, NULL);
}
/**
* librdf_node_to_counted_string:
* @node: the node object
* @len_p: pointer to location to store length
*
* Format the node as a counted string.
*
* Note a new string is allocated which must be freed by the caller.
*
* Return value: a string value representing the node or NULL on failure
**/
unsigned char*
librdf_node_to_counted_string(librdf_node* node, size_t* len_p)
{
unsigned char *uri_string;
unsigned char *datatype_uri_string=NULL;
size_t len, datatype_len, language_len=0;
unsigned char *s, *d;
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
switch(node->type) {
case LIBRDF_NODE_TYPE_RESOURCE:
uri_string=librdf_uri_to_counted_string(node->value.resource.uri, &len);
if(!uri_string)
return NULL;
len +=2;
if(len_p)
*len_p=len;
s=(unsigned char*)LIBRDF_MALLOC(cstring, len+1);
if(!s) {
LIBRDF_FREE(cstring, uri_string);
return NULL;
}
sprintf((char*)s, "[%s]", uri_string);
LIBRDF_FREE(cstring, uri_string);
break;
case LIBRDF_NODE_TYPE_LITERAL:
len=node->value.literal.string_len;
if(node->value.literal.xml_language) {
language_len=node->value.literal.xml_language_len;
len+=1+language_len;
}
if(node->value.literal.datatype_uri) {
datatype_uri_string=librdf_uri_to_counted_string(node->value.literal.datatype_uri, &datatype_len);
len+=4+datatype_len;
}
if(len_p)
*len_p=len;
s=(unsigned char*)LIBRDF_MALLOC(cstring, len+1);
if(!s)
return NULL;
/* use strcpy here to add \0 to end of literal string */
d=s;
strncpy((char*)d, (const char*)node->value.literal.string, node->value.literal.string_len);
d+= node->value.literal.string_len;
if(node->value.literal.xml_language) {
*d++='@';
strncpy((char*)d, node->value.literal.xml_language, language_len);
d+= language_len;
}
if(datatype_uri_string) {
strncpy((char*)d, "^^<", 3);
d+= 3;
strncpy((char*)d, (const char*)datatype_uri_string, datatype_len);
LIBRDF_FREE(cstring, datatype_uri_string);
d+= datatype_len;
*d++='>';
}
*d='\0';
break;
case LIBRDF_NODE_TYPE_BLANK:
len=node->value.blank.identifier_len + 2;
if(len_p)
*len_p=len;
s=(unsigned char*)LIBRDF_MALLOC(cstring, len+1);
if(!s)
return NULL;
sprintf((char*)s, "(%s)", node->value.blank.identifier);
break;
case LIBRDF_NODE_TYPE_UNKNOWN:
default:
librdf_log(node->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Do not know how to print node type %d", node->type);
return NULL;
}
return s;
}
/**
* librdf_node_print:
* @node: the node
* @fh: file handle
*
* Pretty print the node to a file descriptor.
*
* This method is for debugging and the format of the output should
* not be relied on.
*
**/
void
librdf_node_print(librdf_node* node, FILE *fh)
{
unsigned char* s;
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(node, librdf_node);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(fh, FILE*);
if(!node)
return;
s=librdf_node_to_string(node);
if(!s)
return;
fputs((const char*)s, fh);
LIBRDF_FREE(cstring, s);
}
/**
* librdf_node_get_digest:
* @node: the node object
*
* Get a digest representing a librdf_node.
*
* A new digest object is created which must be freed by the caller.
*
* Return value: a new #librdf_digest object or NULL on failure
**/
librdf_digest*
librdf_node_get_digest(librdf_node* node)
{
librdf_digest* d=NULL;
unsigned char *s;
librdf_world* world=node->world;
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
switch(node->type) {
case LIBRDF_NODE_TYPE_RESOURCE:
d=librdf_uri_get_digest(node->value.resource.uri);
break;
case LIBRDF_NODE_TYPE_LITERAL:
s=node->value.literal.string;
d=librdf_new_digest_from_factory(world, world->digest_factory);
if(!d)
return NULL;
librdf_digest_init(d);
librdf_digest_update(d, (unsigned char*)s, node->value.literal.string_len);
librdf_digest_final(d);
break;
case LIBRDF_NODE_TYPE_BLANK:
case LIBRDF_NODE_TYPE_UNKNOWN:
default:
librdf_log(world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Do not know how to make digest for node type %d",
node->type);
return NULL;
}
return d;
}
/**
* librdf_node_equals:
* @first_node: first #librdf_node node
* @second_node: second #librdf_node node
*
* Compare two librdf_node objects for equality.
*
* Note - for literal nodes, XML language, XML space and well-formness are
* presently ignored in the comparison.
*
* Return value: non 0 if nodes are equal. 0 if not-equal or failure
**/
int
librdf_node_equals(librdf_node* first_node, librdf_node* second_node)
{
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(first_node, librdf_node, 0);
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(second_node, librdf_node, 0);
if(!first_node || !second_node)
return 0;
return (first_node == second_node);
}
/**
* librdf_node_encode:
* @node: the node to serialise
* @buffer: the buffer to use
* @length: buffer size
*
* Serialise a node into a buffer.
*
* Encodes the given node 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.
*
* If the node cannot be encoded due to restrictions of the encoding
* format, a redland error is generated
*
* Return value: the number of bytes written or 0 on failure.
**/
size_t
librdf_node_encode(librdf_node* node, unsigned char *buffer, size_t length)
{
size_t total_length=0;
unsigned char *string;
size_t string_length;
size_t language_length=0;
unsigned char *datatype_uri_string=NULL;
size_t datatype_uri_length=0;
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
switch(node->type) {
case LIBRDF_NODE_TYPE_RESOURCE:
string=(unsigned char*)librdf_uri_as_counted_string(node->value.resource.uri, &string_length);
total_length= 3 + string_length + 1; /* +1 for \0 at end */
if(length && total_length > length)
return 0;
if(string_length > 0xFFFF) {
librdf_log(node->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Cannot encode a URI string of %d bytes length",
(int)string_length);
return 0;
}
if(buffer) {
buffer[0]='R';
buffer[1]=(string_length & 0xff00) >> 8;
buffer[2]=(string_length & 0x00ff);
strcpy((char*)buffer+3, (char*)string);
}
break;
case LIBRDF_NODE_TYPE_LITERAL:
string=(unsigned char*)node->value.literal.string;
string_length=node->value.literal.string_len;
if(node->value.literal.xml_language)
language_length=node->value.literal.xml_language_len;
if(node->value.literal.datatype_uri) {
datatype_uri_string=librdf_uri_as_counted_string(node->value.literal.datatype_uri, &datatype_uri_length);
}
total_length= 6 + string_length + 1; /* +1 for \0 at end */
if(string_length > 0xFFFF) /* for long literal - type 'N' */
total_length+= 2;
if(language_length)
total_length += language_length+1;
if(datatype_uri_length)
total_length += datatype_uri_length+1;
if(length && total_length > length)
return 0;
if(datatype_uri_length > 0xFFFF) {
librdf_log(node->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Cannot encode a datatype URI string of %d bytes length",
(int)datatype_uri_length);
return 0;
}
if(language_length > 0xFF) {
librdf_log(node->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Cannot encode a language string of %d bytes length",
(int)language_length);
return 0;
}
if(buffer) {
if(string_length > 0xFFFF) {
/* long literal type N (string length > 0x10000) */
buffer[0]='N';
buffer[1]=(string_length & 0xff000000) >> 24;
buffer[2]=(string_length & 0x00ff0000) >> 16;
buffer[3]=(string_length & 0x0000ff00) >> 8;
buffer[4]=(string_length & 0x000000ff);
buffer[5]=(datatype_uri_length & 0xff00) >> 8;
buffer[6]=(datatype_uri_length & 0x00ff);
buffer[7]=(language_length & 0x00ff);
buffer += 8;
} else {
/* short literal type M (string length <= 0xFFFF) */
buffer[0]='M';
buffer[1]=(string_length & 0xff00) >> 8;
buffer[2]=(string_length & 0x00ff);
buffer[3]=(datatype_uri_length & 0xff00) >> 8;
buffer[4]=(datatype_uri_length & 0x00ff);
buffer[5]=(language_length & 0x00ff);
buffer += 6;
}
strcpy((char*)buffer, (const char*)string);
buffer += string_length+1;
if(datatype_uri_length) {
strcpy((char*)buffer, (const char*)datatype_uri_string);
buffer += datatype_uri_length+1;
}
if(language_length)
strcpy((char*)buffer, (const char*)node->value.literal.xml_language);
} /* end if buffer */
break;
case LIBRDF_NODE_TYPE_BLANK:
string=(unsigned char*)node->value.blank.identifier;
string_length=node->value.blank.identifier_len;
total_length= 3 + string_length + 1; /* +1 for \0 at end */
if(length && total_length > length)
return 0;
if(string_length > 0xFFFF) {
librdf_log(node->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Cannot encode a blank node identifier string of %d bytes length",
(int)string_length);
return 0;
}
if(buffer) {
buffer[0]='B';
buffer[1]=(string_length & 0xff00) >> 8;
buffer[2]=(string_length & 0x00ff);
strcpy((char*)buffer+3, (const char*)string);
}
break;
case LIBRDF_NODE_TYPE_UNKNOWN:
default:
librdf_log(node->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Do not know how to encode node type %d", node->type);
return 0;
}
return total_length;
}
/**
* librdf_node_decode:
* @world: librdf_world
* @size_p: pointer to bytes used or NULL
* @buffer: the buffer to use
* @length: buffer size
*
* Deserialise a node from a buffer.
*
* Decodes the serialised node (as created by librdf_node_encode() )
* from the given buffer.
*
* Return value: new node or NULL on failure (bad encoding, allocation failure)
**/
librdf_node*
librdf_node_decode(librdf_world *world,
size_t* size_p, unsigned char *buffer, size_t length)
{
int is_wf_xml;
size_t string_length;
size_t total_length;
size_t language_length;
unsigned char *datatype_uri_string=NULL;
size_t datatype_uri_length;
librdf_uri* datatype_uri=NULL;
unsigned char *language=NULL;
int status=0;
librdf_node* node=NULL;
librdf_world_open(world);
/* absolute minimum - first byte is type */
if (length < 1)
return NULL;
total_length=0;
switch(buffer[0]) {
case 'R': /* LIBRDF_NODE_TYPE_RESOURCE */
/* min */
if(length < 3)
return NULL;
string_length=(buffer[1] << 8) | buffer[2];
total_length = 3 + string_length + 1;
node = librdf_new_node_from_uri_string(world, buffer+3);
break;
case 'L': /* Old encoding form for LIBRDF_NODE_TYPE_LITERAL */
/* min */
if(length < 6)
return NULL;
is_wf_xml=(buffer[1] & 0xf0)>>8;
string_length=(buffer[2] << 8) | buffer[3];
language_length=buffer[5];
total_length= 6 + string_length + 1; /* +1 for \0 at end */
if(language_length) {
language = buffer + total_length;
total_length += language_length+1;
}
node=librdf_new_node_from_typed_counted_literal(world,
buffer+6,
string_length,
(const char*)language,
language_length,
is_wf_xml ? LIBRDF_RS_XMLLiteral_URI(world) : NULL);
break;
case 'M': /* LIBRDF_NODE_TYPE_LITERAL 0.9.12+ */
/* min */
if(length < 6)
return NULL;
string_length=(buffer[1] << 8) | buffer[2];
datatype_uri_length=(buffer[3] << 8) | buffer[4];
language_length=buffer[5];
total_length= 6 + string_length + 1; /* +1 for \0 at end */
if(datatype_uri_length) {
datatype_uri_string = buffer + total_length;
total_length += datatype_uri_length+1;
}
if(language_length) {
language = buffer + total_length;
total_length += language_length+1;
}
if(datatype_uri_string)
datatype_uri=librdf_new_uri(world, datatype_uri_string);
node=librdf_new_node_from_typed_counted_literal(world,
buffer+6,
string_length,
(const char*)language,
language_length,
datatype_uri);
if(datatype_uri)
librdf_free_uri(datatype_uri);
if(status)
return NULL;
break;
case 'N': /* LIBRDF_NODE_TYPE_LITERAL - redland 1.0.5+ (long literal) */
/* min */
if(length < 8)
return NULL;
string_length=(buffer[1] << 24) | (buffer[2] << 16) | (buffer[3] << 8) | buffer[4];
datatype_uri_length=(buffer[5] << 8) | buffer[6];
language_length=buffer[7];
total_length= 8 + string_length + 1; /* +1 for \0 at end */
if(datatype_uri_length) {
datatype_uri_string = buffer + total_length;
total_length += datatype_uri_length+1;
}
if(language_length) {
language = buffer + total_length;
total_length += language_length+1;
}
if(datatype_uri_string)
datatype_uri=librdf_new_uri(world, datatype_uri_string);
node=librdf_new_node_from_typed_counted_literal(world,
buffer+8,
string_length,
(const char*)language,
language_length,
datatype_uri);
if(datatype_uri)
librdf_free_uri(datatype_uri);
if(status)
return NULL;
break;
case 'B': /* LIBRDF_NODE_TYPE_BLANK */
/* min */
if(length < 3)
return NULL;
string_length=(buffer[1] << 8) | buffer[2];
total_length= 3 + string_length + 1; /* +1 for \0 at end */
node = librdf_new_node_from_blank_identifier(world, buffer+3);
break;
default:
librdf_log(world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Illegal node encoding '%c' seen", buffer[0]);
return NULL;
}
if(size_p)
*size_p=total_length;
return node;
}
/* iterator over a static array of nodes; - mostly for testing */
static int librdf_node_static_iterator_is_end(void* iterator);
static int librdf_node_static_iterator_next_method(void* iterator);
static void* librdf_node_static_iterator_get_method(void* iterator, int flags);
static void librdf_node_static_iterator_finished(void* iterator);
typedef struct {
librdf_world *world;
librdf_node** nodes; /* static array of nodes; shared */
int size; /* size of above array */
int current; /* index into above array */
} librdf_node_static_iterator_context;
static int
librdf_node_static_iterator_is_end(void* iterator)
{
librdf_node_static_iterator_context* context=(librdf_node_static_iterator_context*)iterator;
return (context->current > context->size-1);
}
static int
librdf_node_static_iterator_next_method(void* iterator)
{
librdf_node_static_iterator_context* context=(librdf_node_static_iterator_context*)iterator;
if(context->current > context->size-1)
return 1;
context->current++;
return 0;
}
static void*
librdf_node_static_iterator_get_method(void* iterator, int flags)
{
librdf_node_static_iterator_context* context=(librdf_node_static_iterator_context*)iterator;
if(context->current > context->size-1)
return NULL;
switch(flags) {
case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
return (void*)context->nodes[context->current];
case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT:
return NULL;
default:
librdf_log(context->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_NODE, NULL,
"Unknown iterator method flag %d", flags);
return NULL;
}
}
static void
librdf_node_static_iterator_finished(void* iterator)
{
librdf_node_static_iterator_context* context=(librdf_node_static_iterator_context*)iterator;
LIBRDF_FREE(librdf_node_static_iterator_context, context);
}
/**
* librdf_node_static_iterator_create:
* @nodes: static array of #librdf_node objects
* @size: size of array
*
* Create an iterator over an array of nodes.
*
* This creates an iterator for an existing static array of librdf_node
* objects. It is mostly intended for testing iterator code.
*
* Return value: a #librdf_iterator serialization of the nodes or NULL on failure
**/
librdf_iterator*
librdf_node_static_iterator_create(librdf_node** nodes,
int size)
{
librdf_node_static_iterator_context* context;
librdf_iterator* iterator;
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(nodes, librdf_node**, NULL);
context=(librdf_node_static_iterator_context*)LIBRDF_CALLOC(librdf_node_static_iterator_context, 1, sizeof(librdf_node_static_iterator_context));
if(!context)
return NULL;
context->nodes=nodes;
context->size=size;
context->current=0;
iterator=librdf_new_iterator(nodes[0]->world,
(void*)context,
librdf_node_static_iterator_is_end,
librdf_node_static_iterator_next_method,
librdf_node_static_iterator_get_method,
librdf_node_static_iterator_finished);
if(!iterator)
librdf_node_static_iterator_finished(context);
return iterator;
}
#endif
/* TEST CODE */
#ifdef STANDALONE
/* one more prototype */
int main(int argc, char *argv[]);
static void
dump_node_as_C(FILE* fh, const char* var, void *buffer, int size) {
int i;
unsigned char* p=(unsigned char*)buffer;
fprintf(fh, "const unsigned char %s[%d] = {", var, size);
for (i=0; i < size; i++) {
if(i)
fputs(", ", fh);
fprintf(fh, "0x%02x", p[i]);
}
fputs("};\n", fh);
}
static int
check_node(const char* program, const unsigned char *expected,
void *buffer, size_t size) {
unsigned int i;
for(i=0; i< size; i++) {
unsigned char c=((unsigned char*)buffer)[i];
if(c != expected[i]) {
fprintf(stderr, "%s: Encoding node byte %d: 0x%02x expected 0x%02x\n",
program, i, c, expected[i]);
return(1);
}
}
return(0);
}
static const char *hp_string1="http://purl.org/net/dajobe/";
static const char *hp_string2="http://purl.org/net/dajobe/";
static const char *lit_string="Dave Beckett";
static const char *genid="genid42";
static const char *datatype_lit_string="Datatyped literal value";
static const char *datatype_uri_string="http://example.org/datatypeURI";
/* Node Encoded (type R) version of hp_string1 */
static const unsigned char hp_uri_encoded[31] = {0x52, 0x00, 0x1b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x61, 0x6a, 0x6f, 0x62, 0x65, 0x2f, 0x00};
/* Node Encoded (type M) version of typed literal with literal value
* datatype_lit_string and datatype URI datatype_uri_string */
static const unsigned char datatyped_literal_M_encoded[61] = {0x4d, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x44, 0x61, 0x74, 0x61, 0x74, 0x79, 0x70, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x74, 0x79, 0x70, 0x65, 0x55, 0x52, 0x49, 0x00};
/* Node Encoded (type N) version of big 100,000-length literal
* (just the first 32 bytes, the rest are 0x58 'X')
*/
const unsigned char big_literal_N_encoded[32] = {0x4e, 0x00, 0x01, 0x86, 0xa0, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58};
int
main(int argc, char *argv[])
{
librdf_node *node, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
librdf_uri *uri, *uri2;
int size, size2;
unsigned char *buffer;
librdf_world *world;
size_t big_literal_length;
unsigned char *big_literal;
unsigned int i;
const char *program=librdf_basename((const char*)argv[0]);
world=librdf_new_world();
librdf_world_open(world);
fprintf(stdout, "%s: Creating home page node from string\n", program);
node=librdf_new_node_from_uri_string(world, (const unsigned char*)hp_string1);
if(!node) {
fprintf(stderr, "%s: librdf_new_node_from_uri_string failed\n", program);
return(1);
}
fprintf(stdout, "%s: Home page URI is ", program);
librdf_uri_print(librdf_node_get_uri(node), stdout);
fputc('\n', stdout);
fprintf(stdout, "%s: Creating URI from string '%s'\n", program,
hp_string2);
uri=librdf_new_uri(world, (const unsigned char*)hp_string2);
fprintf(stdout, "%s: Setting node URI to new URI ", program);
librdf_uri_print(uri, stdout);
fputc('\n', stdout);
librdf_free_uri(uri);
fprintf(stdout, "%s: Node is: ", program);
librdf_node_print(node, stdout);
fputc('\n', stdout);
size=librdf_node_encode(node, NULL, 0);
fprintf(stdout, "%s: Encoding node requires %d bytes\n", program, size);
buffer=(unsigned char*)LIBRDF_MALLOC(cstring, size);
fprintf(stdout, "%s: Encoding node in buffer\n", program);
size2=librdf_node_encode(node, buffer, size);
if(size2 != size) {
fprintf(stderr, "%s: Encoding node used %d bytes, expected it to use %d\n", program, size2, size);
return(1);
}
if(0)
dump_node_as_C(stdout, "hp_uri_encoded", buffer, size);
if(check_node(program, hp_uri_encoded, buffer, size))
return(1);
fprintf(stdout, "%s: Creating new node\n", program);
fprintf(stdout, "%s: Decoding node from buffer\n", program);
if(!(node2=librdf_node_decode(world, NULL, buffer, size))) {
fprintf(stderr, "%s: Decoding node failed\n", program);
return(1);
}
LIBRDF_FREE(cstring, buffer);
fprintf(stdout, "%s: New node is: ", program);
librdf_node_print(node2, stdout);
fputc('\n', stdout);
fprintf(stdout, "%s: Creating new literal string node\n", program);
node3=librdf_new_node_from_literal(world, (const unsigned char*)lit_string, NULL, 0);
if(!node3) {
fprintf(stderr, "%s: librdf_new_node_from_literal failed\n", program);
return(1);
}
buffer=(unsigned char*)librdf_node_get_literal_value_as_latin1(node3);
if(!buffer) {
fprintf(stderr, "%s: Failed to get literal string value as Latin-1\n", program);
return(1);
}
fprintf(stdout, "%s: Node literal string value (Latin-1) is: '%s'\n",
program, buffer);
LIBRDF_FREE(cstring, buffer);
fprintf(stdout, "%s: Creating new blank node with identifier %s\n", program, genid);
node4=librdf_new_node_from_blank_identifier(world, (const unsigned char*)genid);
if(!node4) {
fprintf(stderr, "%s: librdf_new_node_from_blank_identifier failed\n", program);
return(1);
}
buffer=librdf_node_get_blank_identifier(node4);
if(!buffer) {
fprintf(stderr, "%s: Failed to get blank node identifier\n", program);
return(1);
}
fprintf(stdout, "%s: Node identifier is: '%s'\n", program, buffer);
node5=librdf_new_node_from_node(node4);
if(!node5) {
fprintf(stderr, "%s: Failed to make new blank node from old one\n", program);
return(1);
}
buffer=librdf_node_get_blank_identifier(node5);
if(!buffer) {
fprintf(stderr, "%s: Failed to get copied blank node identifier\n", program);
return(1);
}
fprintf(stdout, "%s: Copied node identifier is: '%s'\n", program, buffer);
uri2=librdf_new_uri(world, (const unsigned char*)datatype_uri_string);
node6=librdf_new_node_from_typed_literal(world,
(const unsigned char*)datatype_lit_string,
NULL, uri2);
librdf_free_uri(uri2);
size=librdf_node_encode(node6, NULL, 0);
fprintf(stdout, "%s: Encoding typed node requires %d bytes\n", program, size);
buffer=(unsigned char*)LIBRDF_MALLOC(cstring, size);
fprintf(stdout, "%s: Encoding typed node in buffer\n", program);
size2=librdf_node_encode(node6, (unsigned char*)buffer, size);
if(size2 != size) {
fprintf(stderr, "%s: Encoding typed node used %d bytes, expected it to use %d\n", program, size2, size);
return(1);
}
if(0)
dump_node_as_C(stdout, "datatyped_literal_M_encoded", buffer, size);
if(check_node(program, datatyped_literal_M_encoded, buffer, size))
return(1);
fprintf(stdout, "%s: Decoding typed node from buffer\n", program);
if(!(node7=librdf_node_decode(world, NULL, (unsigned char*)buffer, size))) {
fprintf(stderr, "%s: Decoding typed node failed\n", program);
return(1);
}
LIBRDF_FREE(cstring, buffer);
if(librdf_new_node_from_typed_literal(world,
(const unsigned char*)"Datatyped literal value",
"en-GB", uri2)) {
fprintf(stderr, "%s: Unexpected success allowing a datatyped literal with a language\n", program);
return(1);
}
if(librdf_new_node_from_literal(world,
(const unsigned char*)"XML literal value",
"en-GB", 1)) {
fprintf(stderr, "%s: Unexpected success allowing an XML literal with a language\n", program);
return(1);
}
big_literal_length=100000;
big_literal=(unsigned char *)LIBRDF_MALLOC(cstring, big_literal_length+1);
for(i=0; i<big_literal_length; i++)
big_literal[i]='X';
node8=librdf_new_node_from_typed_counted_literal(world,
big_literal, big_literal_length,
NULL, 0, NULL);
if(!node8) {
fprintf(stderr, "%s: Failed to make big %d byte literal\n", program,
(int)big_literal_length);
return(1);
}
LIBRDF_FREE(cstring, big_literal);
size=librdf_node_encode(node8, NULL, 0);
fprintf(stdout, "%s: Encoding big literal node requires %d bytes\n", program, size);
buffer=(unsigned char*)LIBRDF_MALLOC(cstring, size);
fprintf(stdout, "%s: Encoding big literal node in buffer\n", program);
size2=librdf_node_encode(node8, (unsigned char*)buffer, size);
if(size2 != size) {
fprintf(stderr, "%s: Encoding big literal node used %d bytes, expected it to use %d\n", program, size2, size);
return(1);
}
/* Just check first 32 bytes */
if(0)
dump_node_as_C(stdout, "big_literal_N_encoded", buffer, 32);
if(check_node(program, big_literal_N_encoded, buffer, 32))
return(1);
LIBRDF_FREE(cstring, buffer);
fprintf(stdout, "%s: Freeing nodes\n", program);
librdf_free_node(node8);
librdf_free_node(node7);
librdf_free_node(node6);
librdf_free_node(node5);
librdf_free_node(node4);
librdf_free_node(node3);
librdf_free_node(node2);
librdf_free_node(node);
librdf_free_world(world);
/* keep gcc -Wall happy */
return(0);
}
#endif