/* -*- 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 #endif #ifdef WIN32 #include #endif #include #include #ifdef HAVE_STDLIB_H #include /* for abort() as used in errors */ #endif #include /* needed for utf8 functions and definition of 'byte' */ #include #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; inodes_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; inodes_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", "", "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