mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-04 08:04:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1949 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1949 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* -*- Mode: c; c-basic-offset: 2 -*-
 | 
						|
 *
 | 
						|
 * rdf_hash.c - RDF Hash interface - set of (key: value) pairs with dups
 | 
						|
 *
 | 
						|
 * 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>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <ctype.h>
 | 
						|
#include <sys/types.h>
 | 
						|
 | 
						|
#ifdef HAVE_STDLIB_H
 | 
						|
#include <stdlib.h> /* for strtol */
 | 
						|
#endif
 | 
						|
 | 
						|
#include <redland.h>
 | 
						|
 | 
						|
#include <rdf_hash.h>
 | 
						|
#include <rdf_heuristics.h>
 | 
						|
 | 
						|
#ifndef STANDALONE
 | 
						|
 | 
						|
/* prototypes for helper functions */
 | 
						|
static void librdf_delete_hash_factories(librdf_world *world);
 | 
						|
 | 
						|
static void librdf_init_hash_datums(librdf_world *world);
 | 
						|
static void librdf_free_hash_datums(librdf_world *world);
 | 
						|
 | 
						|
 | 
						|
/* prototypes for iterator for getting all keys and values */
 | 
						|
static int librdf_hash_get_all_iterator_is_end(void* iterator);
 | 
						|
static int librdf_hash_get_all_iterator_next_method(void* iterator);
 | 
						|
static void* librdf_hash_get_all_iterator_get_method(void* iterator, int);
 | 
						|
static void librdf_hash_get_all_iterator_finished(void* iterator);
 | 
						|
 | 
						|
/* prototypes for iterator for getting all keys */
 | 
						|
static int librdf_hash_keys_iterator_is_end(void* iterator);
 | 
						|
static int librdf_hash_keys_iterator_next_method(void* iterator);
 | 
						|
static void* librdf_hash_keys_iterator_get_method(void* iterator, int);
 | 
						|
static void librdf_hash_keys_iterator_finished(void* iterator);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_init_hash:
 | 
						|
 *
 | 
						|
 * INTERNAL - Initialise the hash module.
 | 
						|
 *
 | 
						|
 * Initialises and registers all
 | 
						|
 * compiled hash modules.  Must be called before using any of the hash
 | 
						|
 * factory functions such as librdf_get_hash_factory()
 | 
						|
 * @world: redland world object
 | 
						|
 **/
 | 
						|
void
 | 
						|
librdf_init_hash(librdf_world *world) 
 | 
						|
{
 | 
						|
  /* Init hash datum cache */
 | 
						|
  librdf_init_hash_datums(world);
 | 
						|
#ifdef HAVE_BDB_HASH
 | 
						|
  librdf_init_hash_bdb(world);
 | 
						|
#endif
 | 
						|
  /* Always have hash in memory implementation available */
 | 
						|
  librdf_init_hash_memory(world);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_finish_hash:
 | 
						|
 * @world: redland world object
 | 
						|
 *
 | 
						|
 * INTERNAL - Terminate the hash module.
 | 
						|
 *
 | 
						|
 **/
 | 
						|
void
 | 
						|
librdf_finish_hash(librdf_world *world) 
 | 
						|
{
 | 
						|
  librdf_delete_hash_factories(world);
 | 
						|
  librdf_free_hash_datums(world);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* helper functions */
 | 
						|
static void
 | 
						|
librdf_delete_hash_factories(librdf_world *world)
 | 
						|
{
 | 
						|
  librdf_hash_factory *factory, *next;
 | 
						|
  
 | 
						|
  for(factory=world->hashes; factory; factory=next) {
 | 
						|
    next=factory->next;
 | 
						|
    LIBRDF_FREE(librdf_hash_factory, factory->name);
 | 
						|
    LIBRDF_FREE(librdf_hash_factory, factory);
 | 
						|
  }
 | 
						|
  world->hashes=NULL;
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* hash datums structures */
 | 
						|
 | 
						|
static void
 | 
						|
librdf_init_hash_datums(librdf_world *world)
 | 
						|
{
 | 
						|
  world->hash_datums_list=NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
librdf_free_hash_datums(librdf_world *world)
 | 
						|
{
 | 
						|
  librdf_hash_datum *datum, *next;
 | 
						|
  
 | 
						|
  for(datum=world->hash_datums_list; datum; datum=next) {
 | 
						|
    next=datum->next;
 | 
						|
    LIBRDF_FREE(librdf_hash_datum, datum);
 | 
						|
  }
 | 
						|
  world->hash_datums_list=NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_new_hash_datum:
 | 
						|
 * @world: redland world object
 | 
						|
 * @data: data to store
 | 
						|
 * @size: size of data
 | 
						|
 *
 | 
						|
 * Constructor - Create a new #librdf_hash_datum object.
 | 
						|
 * 
 | 
						|
 * Return value: New #librdf_hash_datum object or NULL on failure
 | 
						|
 **/
 | 
						|
librdf_hash_datum*
 | 
						|
librdf_new_hash_datum(librdf_world *world, void *data, size_t size)
 | 
						|
{
 | 
						|
  librdf_hash_datum *datum;
 | 
						|
 | 
						|
  librdf_world_open(world);
 | 
						|
 | 
						|
  /* get one from free list, or allocate new one */ 
 | 
						|
  if((datum=world->hash_datums_list)) {
 | 
						|
    world->hash_datums_list=datum->next;
 | 
						|
  } else {
 | 
						|
    datum=(librdf_hash_datum*)LIBRDF_CALLOC(librdf_hash_datum, 1, sizeof(librdf_hash_datum));
 | 
						|
    if(datum)
 | 
						|
      datum->world=world;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if(datum) {
 | 
						|
    datum->data=data;
 | 
						|
    datum->size=size;
 | 
						|
  }
 | 
						|
 | 
						|
  return datum;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_free_hash_datum:
 | 
						|
 * @datum: hash datum object
 | 
						|
 *
 | 
						|
 * Destructor - destroy a #librdf_hash_datum object.
 | 
						|
 *
 | 
						|
 **/
 | 
						|
void
 | 
						|
librdf_free_hash_datum(librdf_hash_datum *datum) 
 | 
						|
{
 | 
						|
  if(datum->data)
 | 
						|
    LIBRDF_FREE(cstring, datum->data);
 | 
						|
  datum->next=datum->world->hash_datums_list;
 | 
						|
  datum->world->hash_datums_list=datum;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* class methods */
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_register_factory:
 | 
						|
 * @world: redland world object
 | 
						|
 * @name: the hash factory name
 | 
						|
 * @factory: pointer to function to call to register the factory
 | 
						|
 *
 | 
						|
 * Register a hash factory.
 | 
						|
 * 
 | 
						|
 **/
 | 
						|
void
 | 
						|
librdf_hash_register_factory(librdf_world *world, const char *name,
 | 
						|
                             void (*factory) (librdf_hash_factory*)) 
 | 
						|
{
 | 
						|
  librdf_hash_factory *hash;
 | 
						|
 | 
						|
  librdf_world_open(world);
 | 
						|
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
  LIBRDF_DEBUG2("Received registration for hash %s\n", name);
 | 
						|
#endif
 | 
						|
  
 | 
						|
  for(hash = world->hashes; hash; hash = hash->next ) {
 | 
						|
    if(!strcmp(hash->name, name)) {
 | 
						|
      librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
 | 
						|
                 "hash %s already registered", hash->name);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  hash=(librdf_hash_factory*)LIBRDF_CALLOC(librdf_hash_factory, 1,
 | 
						|
                                           sizeof(librdf_hash_factory));
 | 
						|
  if(!hash)
 | 
						|
    goto oom;
 | 
						|
  
 | 
						|
  hash->name=(char*)LIBRDF_MALLOC(cstring, strlen(name)+1);
 | 
						|
  if(!hash->name)
 | 
						|
    goto oom_tidy;
 | 
						|
  strcpy(hash->name, name);
 | 
						|
  
 | 
						|
  hash->next = world->hashes;
 | 
						|
  world->hashes = hash;
 | 
						|
  
 | 
						|
  /* Call the hash registration function on the new object */
 | 
						|
  (*factory)(hash);
 | 
						|
  
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
  LIBRDF_DEBUG3("%s has context size %d\n", name, hash->context_length);
 | 
						|
#endif
 | 
						|
 | 
						|
  return;
 | 
						|
 | 
						|
  oom_tidy:
 | 
						|
  LIBRDF_FREE(librdf_hash, hash);
 | 
						|
  oom:
 | 
						|
  LIBRDF_FATAL1(world, LIBRDF_FROM_HASH, "Out of memory");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_get_hash_factory:
 | 
						|
 * @world: redland world object
 | 
						|
 * @name: the factory name or NULL for the default factory
 | 
						|
 *
 | 
						|
 * Get a hash factory by name.
 | 
						|
 * 
 | 
						|
 * FIXME: several bits of code assume the default hash factory is
 | 
						|
 * in memory.
 | 
						|
 *
 | 
						|
 * Return value: the factory object or NULL if there is no such factory
 | 
						|
 **/
 | 
						|
librdf_hash_factory*
 | 
						|
librdf_get_hash_factory(librdf_world *world, const char *name) 
 | 
						|
{
 | 
						|
  librdf_hash_factory *factory;
 | 
						|
 | 
						|
  librdf_world_open(world);
 | 
						|
 | 
						|
  /* return 1st hash if no particular one wanted - why? */
 | 
						|
  if(!name) {
 | 
						|
    factory=world->hashes;
 | 
						|
    if(!factory) {
 | 
						|
      LIBRDF_DEBUG1("No (default) hashes registered\n");
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    for(factory=world->hashes; factory; factory=factory->next) {
 | 
						|
      if(!strcmp(factory->name, name)) {
 | 
						|
	break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    /* else FACTORY name not found */
 | 
						|
    if(!factory)
 | 
						|
      return NULL;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return factory;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_new_hash:
 | 
						|
 * @world: redland world object
 | 
						|
 * @name: factory name
 | 
						|
 *
 | 
						|
 * Constructor - create a new #librdf_hash object.
 | 
						|
 *
 | 
						|
 * Return value: a new #librdf_hash object or NULL on failure
 | 
						|
 */
 | 
						|
librdf_hash*
 | 
						|
librdf_new_hash(librdf_world *world, const char* name)
 | 
						|
{
 | 
						|
  librdf_hash_factory *factory;
 | 
						|
 | 
						|
  librdf_world_open(world);
 | 
						|
 | 
						|
  factory=librdf_get_hash_factory(world, name);
 | 
						|
  if(!factory)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  return librdf_new_hash_from_factory(world, factory);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_new_hash_from_factory:
 | 
						|
 * @world: redland world object
 | 
						|
 * @factory: the factory to use to construct the hash
 | 
						|
 *
 | 
						|
 * Constructor - create a new #librdf_hash object from a factory.
 | 
						|
 *
 | 
						|
 * Return value: a new #librdf_hash object or NULL on failure
 | 
						|
 */
 | 
						|
librdf_hash*
 | 
						|
librdf_new_hash_from_factory(librdf_world *world,
 | 
						|
                             librdf_hash_factory* factory)
 | 
						|
{
 | 
						|
  librdf_hash* h;
 | 
						|
 | 
						|
  librdf_world_open(world);
 | 
						|
 | 
						|
  h=(librdf_hash*)LIBRDF_CALLOC(librdf_hash, sizeof(librdf_hash), 1);
 | 
						|
  if(!h)
 | 
						|
    return NULL;
 | 
						|
  
 | 
						|
  h->context=(char*)LIBRDF_CALLOC(librdf_hash_context, 1,
 | 
						|
                                  factory->context_length);
 | 
						|
  if(!h->context) {
 | 
						|
    librdf_free_hash(h);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  h->world=world;
 | 
						|
  
 | 
						|
  h->factory=factory;
 | 
						|
 | 
						|
  /* call factory constructor */
 | 
						|
  if(h->factory->create(h, h->context)) {
 | 
						|
    librdf_free_hash(h);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return h;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_new_hash_from_string:
 | 
						|
 * @world: redland world object
 | 
						|
 * @name: hash name
 | 
						|
 * @string: hash encoded as a string
 | 
						|
 * 
 | 
						|
 * Constructor - create a new #librdf_hash object from a string.
 | 
						|
 *
 | 
						|
 * See #librdf_hash_from_string for the string format.
 | 
						|
 * 
 | 
						|
 * Return value: a new #librdf_hash object or NULL on failure
 | 
						|
 */
 | 
						|
librdf_hash*
 | 
						|
librdf_new_hash_from_string(librdf_world *world, const char *name,
 | 
						|
                            const char *string)
 | 
						|
{
 | 
						|
  librdf_hash* hash;
 | 
						|
 | 
						|
  librdf_world_open(world);
 | 
						|
 | 
						|
  hash=librdf_new_hash(world, name);
 | 
						|
  if(!hash)
 | 
						|
    return NULL;
 | 
						|
  
 | 
						|
  if(librdf_hash_from_string(hash, string)) {
 | 
						|
    librdf_free_hash(hash);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return hash;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_new_hash_from_array_of_strings:
 | 
						|
 * @world: redland world object
 | 
						|
 * @name: hash name
 | 
						|
 * @array: address of the start of the array of char* pointers
 | 
						|
 *
 | 
						|
 * Constructor - create a new #librdf_hash object from an array of strings.
 | 
						|
 *
 | 
						|
 * Return value: a new #librdf_hash object or NULL on failure
 | 
						|
 */
 | 
						|
librdf_hash*
 | 
						|
librdf_new_hash_from_array_of_strings(librdf_world *world, const char *name,
 | 
						|
                                      const char **array)
 | 
						|
{
 | 
						|
  librdf_hash* hash;
 | 
						|
 | 
						|
  librdf_world_open(world);
 | 
						|
 | 
						|
  hash=librdf_new_hash(world, name);
 | 
						|
  if(!hash)
 | 
						|
    return NULL;
 | 
						|
  
 | 
						|
  if(librdf_hash_from_array_of_strings(hash, array)) {
 | 
						|
    librdf_free_hash(hash);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return hash;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_new_hash_from_hash:
 | 
						|
 * @old_hash: the hash to use to construct the hash
 | 
						|
 *
 | 
						|
 * Copy Constructor - create a new #librdf_hash object from an existing one.
 | 
						|
 *
 | 
						|
 * Return value: a new #librdf_hash object or NULL on failure
 | 
						|
 */
 | 
						|
librdf_hash*
 | 
						|
librdf_new_hash_from_hash(librdf_hash* old_hash)
 | 
						|
{
 | 
						|
  librdf_hash* hash;
 | 
						|
  
 | 
						|
  hash=(librdf_hash*)LIBRDF_CALLOC(librdf_hash, sizeof(librdf_hash), 1);
 | 
						|
  if(!hash)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  hash->world=old_hash->world;
 | 
						|
  hash->factory=old_hash->factory;
 | 
						|
 | 
						|
  hash->context=(char*)LIBRDF_CALLOC(librdf_hash_context, 1,
 | 
						|
                                     hash->factory->context_length);
 | 
						|
  if(!hash->context) {
 | 
						|
    librdf_free_hash(hash);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if(old_hash->identifier) {
 | 
						|
    hash->identifier=librdf_heuristic_gen_name(old_hash->identifier);
 | 
						|
    if(!hash->identifier) {
 | 
						|
      librdf_free_hash(hash);
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if(hash->factory->clone(hash, hash->context, hash->identifier,
 | 
						|
                          old_hash->context)) {
 | 
						|
    if(hash->identifier)
 | 
						|
      LIBRDF_FREE(cstring, hash->identifier);
 | 
						|
    librdf_free_hash(hash);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return hash;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_free_hash:
 | 
						|
 * @hash: hash object
 | 
						|
 *
 | 
						|
 * Destructor - destroy a #librdf_hash object.
 | 
						|
 */
 | 
						|
void
 | 
						|
librdf_free_hash(librdf_hash* hash) 
 | 
						|
{
 | 
						|
  if(hash->context) {
 | 
						|
    if(hash->is_open)
 | 
						|
      librdf_hash_close(hash);
 | 
						|
    hash->factory->destroy(hash->context);
 | 
						|
    LIBRDF_FREE(librdf_hash_context, hash->context);
 | 
						|
  }
 | 
						|
  LIBRDF_FREE(librdf_hash, hash);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* methods */
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_open:
 | 
						|
 * @hash: hash object
 | 
						|
 * @identifier: indentifier for the hash factory - usually a URI or file name
 | 
						|
 * @mode: hash access mode
 | 
						|
 * @is_writable: is hash writable?
 | 
						|
 * @is_new: is hash new?
 | 
						|
 * @options: a hash of options for the hash factory or NULL if there are none.
 | 
						|
 *
 | 
						|
 * Start a hash association .
 | 
						|
 * 
 | 
						|
 * This method opens and/or creates a new hash with any resources it
 | 
						|
 * needs.
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_open(librdf_hash* hash, const char *identifier,
 | 
						|
                 int mode, int is_writable, int is_new,
 | 
						|
                 librdf_hash* options) 
 | 
						|
{
 | 
						|
  int status;
 | 
						|
 | 
						|
  if(identifier) {
 | 
						|
    hash->identifier=(char*)LIBRDF_MALLOC(cstring, strlen(identifier)+1);
 | 
						|
    if(!hash->identifier)
 | 
						|
      return 1;
 | 
						|
    strcpy(hash->identifier, identifier);
 | 
						|
  }
 | 
						|
  status=hash->factory->open(hash->context, identifier, 
 | 
						|
                             mode, is_writable, is_new, 
 | 
						|
                             options);
 | 
						|
  if(!status)
 | 
						|
    hash->is_open=1;
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_close:
 | 
						|
 * @hash: hash object
 | 
						|
 *
 | 
						|
 * End a hash association.
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_close(librdf_hash* hash)
 | 
						|
{
 | 
						|
  hash->is_open=0;
 | 
						|
  if(hash->identifier) {
 | 
						|
    LIBRDF_FREE(cstring,hash->identifier);
 | 
						|
    hash->identifier=NULL;
 | 
						|
  }
 | 
						|
  return hash->factory->close(hash->context);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_values_count:
 | 
						|
 * @hash: 
 | 
						|
 *
 | 
						|
 * Get the number of values in the hash.
 | 
						|
 * 
 | 
						|
 * Return value: integer number of values in the hash or <0 if cannot be determined
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_values_count(librdf_hash* hash) 
 | 
						|
{
 | 
						|
  return hash->factory->values_count(hash->context);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_get:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: pointer to key
 | 
						|
 *
 | 
						|
 * Retrieve one value from hash for a given key as string.
 | 
						|
 * 
 | 
						|
 * The value returned is from newly allocated memory which the
 | 
						|
 * caller must free.
 | 
						|
 * 
 | 
						|
 * Return value: the value or NULL on failure
 | 
						|
 **/
 | 
						|
char*
 | 
						|
librdf_hash_get(librdf_hash* hash, const char *key)
 | 
						|
{
 | 
						|
  librdf_hash_datum *hd_key, *hd_value;
 | 
						|
  char *value=NULL;
 | 
						|
 | 
						|
  hd_key=librdf_new_hash_datum(hash->world, (void*)key, strlen(key));
 | 
						|
  if(!hd_key)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  hd_value=librdf_hash_get_one(hash, hd_key);
 | 
						|
 | 
						|
  if(hd_value) {
 | 
						|
    if(hd_value->data) {
 | 
						|
      value=(char*)LIBRDF_MALLOC(cstring, hd_value->size+1);
 | 
						|
      if(value) {
 | 
						|
        /* Copy into new null terminated string for userland */
 | 
						|
        memcpy(value, hd_value->data, hd_value->size);
 | 
						|
        value[hd_value->size]='\0';
 | 
						|
      }
 | 
						|
    }
 | 
						|
    librdf_free_hash_datum(hd_value);
 | 
						|
  }
 | 
						|
 | 
						|
  /* don't free user key */
 | 
						|
  hd_key->data=NULL;
 | 
						|
  librdf_free_hash_datum(hd_key);
 | 
						|
 | 
						|
  return value;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_get_one:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: pointer to key
 | 
						|
 *
 | 
						|
 * Retrieve one value from hash for a given key.
 | 
						|
 * 
 | 
						|
 * The value returned is from newly allocated memory which the
 | 
						|
 * caller must free.
 | 
						|
 * 
 | 
						|
 * Return value: the value or NULL on failure
 | 
						|
 **/
 | 
						|
librdf_hash_datum*
 | 
						|
librdf_hash_get_one(librdf_hash* hash, librdf_hash_datum *key)
 | 
						|
{
 | 
						|
  librdf_hash_datum *value;
 | 
						|
  librdf_hash_cursor *cursor;
 | 
						|
  int status;
 | 
						|
  char *new_value;
 | 
						|
  
 | 
						|
  value=librdf_new_hash_datum(hash->world, NULL, 0);
 | 
						|
  if(!value)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  cursor=librdf_new_hash_cursor(hash);
 | 
						|
  if(!cursor) {
 | 
						|
    librdf_free_hash_datum(value);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  status=librdf_hash_cursor_get_next(cursor, key, value);
 | 
						|
  if(!status) {
 | 
						|
    /* value->data will point to SHARED area, so copy it */
 | 
						|
    new_value=(char*)LIBRDF_MALLOC(cstring, value->size);
 | 
						|
    if(new_value) {
 | 
						|
      memcpy(new_value, value->data, value->size);
 | 
						|
      value->data=new_value;
 | 
						|
    } else {
 | 
						|
      status=1;
 | 
						|
      value->data=NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /* this deletes the data behind the datum */
 | 
						|
  librdf_free_hash_cursor(cursor);
 | 
						|
 | 
						|
  if(status) {
 | 
						|
    librdf_free_hash_datum(value);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return value;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  librdf_hash* hash;
 | 
						|
  librdf_hash_cursor* cursor;
 | 
						|
  librdf_hash_datum *key;
 | 
						|
  librdf_hash_datum *value;
 | 
						|
 | 
						|
  librdf_hash_datum next_key; /* not used if one_key set */
 | 
						|
  librdf_hash_datum next_value;
 | 
						|
  int is_end;
 | 
						|
  int one_key;
 | 
						|
} librdf_hash_get_all_iterator_context;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_get_all:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: pointer to key
 | 
						|
 * @value: pointer to value
 | 
						|
 *
 | 
						|
 * Retrieve all values from hash for a given key.
 | 
						|
 * 
 | 
						|
 * The iterator returns #librdf_hash_datum objects containing the values.
 | 
						|
 * These are newly allocated memory which the caller must free.
 | 
						|
 * 
 | 
						|
 * Return value: a #librdf_iterator serialization of all values or NULL on failure
 | 
						|
 **/
 | 
						|
librdf_iterator*
 | 
						|
librdf_hash_get_all(librdf_hash* hash, 
 | 
						|
                    librdf_hash_datum *key, librdf_hash_datum *value)
 | 
						|
{
 | 
						|
  librdf_hash_get_all_iterator_context* context;
 | 
						|
  int status;
 | 
						|
  librdf_iterator* iterator;
 | 
						|
  
 | 
						|
  context=(librdf_hash_get_all_iterator_context*)LIBRDF_CALLOC(librdf_hash_get_all_iterator_context, 1, sizeof(librdf_hash_get_all_iterator_context));
 | 
						|
  if(!context)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  if(!(context->cursor=librdf_new_hash_cursor(hash))) {
 | 
						|
    librdf_hash_get_all_iterator_finished(context);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if(key->data)
 | 
						|
    context->one_key=1;
 | 
						|
 | 
						|
  context->hash=hash;
 | 
						|
  context->key=key;
 | 
						|
  context->value=value;
 | 
						|
 | 
						|
  if(context->one_key)
 | 
						|
    status=librdf_hash_cursor_set(context->cursor, context->key, 
 | 
						|
                                  &context->next_value);
 | 
						|
  else
 | 
						|
    status=librdf_hash_cursor_get_first(context->cursor, &context->next_key, 
 | 
						|
                                        &context->next_value);
 | 
						|
 | 
						|
  context->is_end=(status != 0);
 | 
						|
  
 | 
						|
  iterator=librdf_new_iterator(hash->world,
 | 
						|
                               (void*)context,
 | 
						|
                               librdf_hash_get_all_iterator_is_end,
 | 
						|
                               librdf_hash_get_all_iterator_next_method,
 | 
						|
                               librdf_hash_get_all_iterator_get_method,
 | 
						|
                               librdf_hash_get_all_iterator_finished);
 | 
						|
  if(!iterator)
 | 
						|
    librdf_hash_get_all_iterator_finished(context);
 | 
						|
  return iterator;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
librdf_hash_get_all_iterator_is_end(void* iterator)
 | 
						|
{
 | 
						|
  librdf_hash_get_all_iterator_context* context=(librdf_hash_get_all_iterator_context*)iterator;
 | 
						|
 | 
						|
  return context->is_end;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
librdf_hash_get_all_iterator_next_method(void* iterator) 
 | 
						|
{
 | 
						|
  librdf_hash_get_all_iterator_context* context=(librdf_hash_get_all_iterator_context*)iterator;
 | 
						|
  int status;
 | 
						|
    
 | 
						|
  if(context->is_end)
 | 
						|
    return 1;
 | 
						|
  
 | 
						|
  /* move on */
 | 
						|
  
 | 
						|
  if(context->one_key)
 | 
						|
    status=librdf_hash_cursor_get_next_value(context->cursor, 
 | 
						|
                                             &context->next_key,
 | 
						|
                                             &context->next_value);
 | 
						|
  else {
 | 
						|
    /* want the next key/value pair, so mark last data as used */
 | 
						|
    context->next_key.data=NULL;
 | 
						|
    status=librdf_hash_cursor_get_next(context->cursor, 
 | 
						|
                                       &context->next_key, 
 | 
						|
                                       &context->next_value);
 | 
						|
  }
 | 
						|
  
 | 
						|
  if(status)
 | 
						|
    context->is_end=1;
 | 
						|
 | 
						|
  return context->is_end;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void*
 | 
						|
librdf_hash_get_all_iterator_get_method(void* iterator, int flags) 
 | 
						|
{
 | 
						|
  librdf_hash_get_all_iterator_context* context=(librdf_hash_get_all_iterator_context*)iterator;
 | 
						|
  void *result=NULL;
 | 
						|
  
 | 
						|
  if(context->is_end)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  switch(flags) {
 | 
						|
    case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
 | 
						|
      /* This is so that librdf_iterator_update_current_element works OK,
 | 
						|
       * since the get_object method isn't used for hashes,
 | 
						|
       * might as well return something useful to signify not-end-of-list.
 | 
						|
       */
 | 
						|
 | 
						|
      result=&context;
 | 
						|
      break;
 | 
						|
 | 
						|
    case LIBRDF_ITERATOR_GET_METHOD_GET_KEY:
 | 
						|
      result=&context->next_key;
 | 
						|
      break;
 | 
						|
      
 | 
						|
    case LIBRDF_ITERATOR_GET_METHOD_GET_VALUE:
 | 
						|
      result=&context->next_value;
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      librdf_log(context->hash->world, 
 | 
						|
                 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
 | 
						|
                 "Unknown iterator method flag %d", flags);
 | 
						|
      result=NULL;
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
librdf_hash_get_all_iterator_finished(void* iterator) 
 | 
						|
{
 | 
						|
  librdf_hash_get_all_iterator_context* context=(librdf_hash_get_all_iterator_context*)iterator;
 | 
						|
 | 
						|
  if(context->cursor)
 | 
						|
    librdf_free_hash_cursor(context->cursor);
 | 
						|
 | 
						|
  if(context->key)
 | 
						|
    context->key->data=NULL;
 | 
						|
 | 
						|
  if(context->value)
 | 
						|
    context->value->data=NULL;
 | 
						|
 | 
						|
  LIBRDF_FREE(librdf_hash_get_all_iterator_context, context);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_get_del:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: pointer to key
 | 
						|
 *
 | 
						|
 * Retrieve one value from hash for a given key as string and remove all values with that key.
 | 
						|
 * 
 | 
						|
 * The value returned is from newly allocated memory which the
 | 
						|
 * caller must free.
 | 
						|
 * 
 | 
						|
 * Return value: the value or NULL on failure
 | 
						|
 **/
 | 
						|
char*
 | 
						|
librdf_hash_get_del(librdf_hash* hash, const char *key)
 | 
						|
{
 | 
						|
  librdf_hash_datum hd_key;
 | 
						|
  char *s;
 | 
						|
  
 | 
						|
  s=librdf_hash_get(hash, key);
 | 
						|
  if(!s)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  hd_key.data=(char*)key;
 | 
						|
  hd_key.size=strlen(key);
 | 
						|
  
 | 
						|
  librdf_hash_delete_all(hash, &hd_key);
 | 
						|
 | 
						|
  return s;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_put:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: key 
 | 
						|
 * @value: value
 | 
						|
 *
 | 
						|
 * Insert key/value pairs into the hash according to flags.
 | 
						|
 * 
 | 
						|
 * The key and values are copied into the hash; the original pointers
 | 
						|
 * can be deleted.
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_put(librdf_hash* hash, librdf_hash_datum *key, 
 | 
						|
                librdf_hash_datum *value)
 | 
						|
{
 | 
						|
  return hash->factory->put(hash->context, key, value);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_exists:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: key
 | 
						|
 * @value: value
 | 
						|
 *
 | 
						|
 * Check if a given key/value is in the hash.
 | 
						|
 * 
 | 
						|
 * Return value: >0 if the key/value exists in the hash, 0 if not, <0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_exists(librdf_hash* hash, librdf_hash_datum *key,
 | 
						|
                   librdf_hash_datum *value)
 | 
						|
{
 | 
						|
  return hash->factory->exists(hash->context, key, value);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_delete:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: key
 | 
						|
 * @value: value
 | 
						|
 *
 | 
						|
 * Delete a key/value pair from the hash.
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure (including pair not present)
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_delete(librdf_hash* hash, librdf_hash_datum *key,
 | 
						|
                   librdf_hash_datum *value)
 | 
						|
{
 | 
						|
  return hash->factory->delete_key_value(hash->context, key, value);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_delete_all:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: key
 | 
						|
 *
 | 
						|
 * Delete a key and all values from the hash.
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure (including pair not present)
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_delete_all(librdf_hash* hash, librdf_hash_datum *key)
 | 
						|
{
 | 
						|
  return hash->factory->delete_key(hash->context, key);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  librdf_hash* hash;
 | 
						|
  librdf_hash_cursor* cursor;
 | 
						|
  librdf_hash_datum *key;
 | 
						|
 | 
						|
  librdf_hash_datum next_key;
 | 
						|
  int is_end;
 | 
						|
} librdf_hash_keys_iterator_context;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_keys:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: pointer to key
 | 
						|
 *
 | 
						|
 * Get the hash keys.
 | 
						|
 * 
 | 
						|
 * The iterator returns #librdf_hash_datum objects containingvalue returned is from newly allocated memory which the
 | 
						|
 * caller must free.
 | 
						|
 * 
 | 
						|
 * Return value: #librdf_iterator serialisation of keys or NULL on failure
 | 
						|
 **/
 | 
						|
librdf_iterator*
 | 
						|
librdf_hash_keys(librdf_hash* hash, librdf_hash_datum *key)
 | 
						|
{
 | 
						|
  librdf_hash_keys_iterator_context* context;
 | 
						|
  int status;
 | 
						|
  librdf_iterator* iterator;
 | 
						|
  
 | 
						|
  context=(librdf_hash_keys_iterator_context*)LIBRDF_CALLOC(librdf_hash_keys_iterator_context, 1, sizeof(librdf_hash_keys_iterator_context));
 | 
						|
  if(!context)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
 | 
						|
  if(!(context->cursor=librdf_new_hash_cursor(hash))) {
 | 
						|
    librdf_hash_keys_iterator_finished(context);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  context->hash=hash;
 | 
						|
  context->key=key;
 | 
						|
 
 | 
						|
  status=librdf_hash_cursor_get_first(context->cursor, &context->next_key, 
 | 
						|
                                      NULL);
 | 
						|
  context->is_end=(status != 0);
 | 
						|
  
 | 
						|
  iterator=librdf_new_iterator(hash->world, 
 | 
						|
                               (void*)context,
 | 
						|
                               librdf_hash_keys_iterator_is_end,
 | 
						|
                               librdf_hash_keys_iterator_next_method,
 | 
						|
                               librdf_hash_keys_iterator_get_method,
 | 
						|
                               librdf_hash_keys_iterator_finished);
 | 
						|
  if(!iterator)
 | 
						|
    librdf_hash_keys_iterator_finished(context);
 | 
						|
  return iterator;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
librdf_hash_keys_iterator_is_end(void* iterator)
 | 
						|
{
 | 
						|
  librdf_hash_keys_iterator_context* context=(librdf_hash_keys_iterator_context*)iterator;
 | 
						|
  
 | 
						|
  if(context->is_end)
 | 
						|
    return 1;
 | 
						|
 | 
						|
  /* have key */
 | 
						|
  if(context->next_key.data)
 | 
						|
    return 0;
 | 
						|
  
 | 
						|
  /* no stored data, so check for it */
 | 
						|
  if(librdf_hash_cursor_get_next(context->cursor, &context->next_key, NULL))
 | 
						|
    context->is_end=1;
 | 
						|
  
 | 
						|
  return context->is_end;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
librdf_hash_keys_iterator_next_method(void* iterator) 
 | 
						|
{
 | 
						|
  librdf_hash_keys_iterator_context* context=(librdf_hash_keys_iterator_context*)iterator;
 | 
						|
 | 
						|
  if(context->is_end)
 | 
						|
    return 1;
 | 
						|
  
 | 
						|
  /* move on */
 | 
						|
 | 
						|
  /* want the next key, so mark last key data as used */
 | 
						|
  context->next_key.data=NULL;
 | 
						|
  if(librdf_hash_cursor_get_next(context->cursor, &context->next_key, NULL))
 | 
						|
    context->is_end=1;
 | 
						|
 | 
						|
  return context->is_end;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void*
 | 
						|
librdf_hash_keys_iterator_get_method(void* iterator, int flags) 
 | 
						|
{
 | 
						|
  librdf_hash_keys_iterator_context* context=(librdf_hash_keys_iterator_context*)iterator;
 | 
						|
  void *result=NULL;
 | 
						|
  
 | 
						|
  if(context->is_end)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  switch(flags) {
 | 
						|
    case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
 | 
						|
      /* This is so that librdf_iterator_update_current_element works OK,
 | 
						|
       * since the get_object method isn't used for hashes,
 | 
						|
       * might as well return something useful to signify not-end-of-list.
 | 
						|
       */
 | 
						|
 | 
						|
      result=&context;
 | 
						|
      break;
 | 
						|
      
 | 
						|
    case LIBRDF_ITERATOR_GET_METHOD_GET_KEY:
 | 
						|
      result=&context->next_key;
 | 
						|
      break;
 | 
						|
      
 | 
						|
    default:
 | 
						|
      result=NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
librdf_hash_keys_iterator_finished(void* iterator) 
 | 
						|
{
 | 
						|
  librdf_hash_keys_iterator_context* context=(librdf_hash_keys_iterator_context*)iterator;
 | 
						|
 | 
						|
  if(context->cursor)
 | 
						|
    librdf_free_hash_cursor(context->cursor);
 | 
						|
 | 
						|
  context->key->data=NULL;
 | 
						|
 | 
						|
  LIBRDF_FREE(librdf_hash_keys_iterator_context, context);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_sync:
 | 
						|
 * @hash: hash object
 | 
						|
 *
 | 
						|
 * Flush any cached information to disk if appropriate.
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_sync(librdf_hash* hash)
 | 
						|
{
 | 
						|
  return hash->factory->sync(hash->context);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_get_fd:
 | 
						|
 * @hash: hash object
 | 
						|
 *
 | 
						|
 * Get the file descriptor for the hash.
 | 
						|
 * 
 | 
						|
 * This returns the file descriptor if it is file based for
 | 
						|
 * use with file locking.
 | 
						|
 * 
 | 
						|
 * Return value: the file descriptor
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_get_fd(librdf_hash* hash)
 | 
						|
{
 | 
						|
  return hash->factory->get_fd(hash->context);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_print:
 | 
						|
 * @hash: the hash
 | 
						|
 * @fh: file handle
 | 
						|
 *
 | 
						|
 * Pretty print the hash to a file descriptor.
 | 
						|
 *
 | 
						|
 **/
 | 
						|
void
 | 
						|
librdf_hash_print(librdf_hash* hash, FILE *fh) 
 | 
						|
{
 | 
						|
  librdf_iterator* iterator;
 | 
						|
  librdf_hash_datum *key, *value;
 | 
						|
  
 | 
						|
  fputs(hash->factory->name, fh);
 | 
						|
  fputs(" hash: {\n", fh);
 | 
						|
 | 
						|
  key=librdf_new_hash_datum(hash->world, NULL, 0);
 | 
						|
  value=librdf_new_hash_datum(hash->world, NULL, 0);
 | 
						|
 | 
						|
  iterator=librdf_hash_get_all(hash, key, value);
 | 
						|
  while(!librdf_iterator_end(iterator)) {
 | 
						|
    librdf_hash_datum *k, *v;
 | 
						|
    size_t l;
 | 
						|
    
 | 
						|
    k=(librdf_hash_datum *)librdf_iterator_get_key(iterator);
 | 
						|
    v=(librdf_hash_datum *)librdf_iterator_get_value(iterator);
 | 
						|
    
 | 
						|
    fputs("  '", fh);
 | 
						|
    l=fwrite(k->data, k->size, 1, fh);
 | 
						|
    if(l != k->size)
 | 
						|
      break;
 | 
						|
    
 | 
						|
    fputs("'=>'", fh);
 | 
						|
    l=fwrite(v->data, v->size, 1, fh);
 | 
						|
    if(l != v->size)
 | 
						|
      break;
 | 
						|
 | 
						|
    fputs("'\n", fh);
 | 
						|
 | 
						|
    librdf_iterator_next(iterator);
 | 
						|
  }
 | 
						|
  if(iterator)
 | 
						|
    librdf_free_iterator(iterator);
 | 
						|
 | 
						|
  librdf_free_hash_datum(value);
 | 
						|
  librdf_free_hash_datum(key);
 | 
						|
 | 
						|
  fputc('}', fh);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_print_keys:
 | 
						|
 * @hash: the hash
 | 
						|
 * @fh: file handle
 | 
						|
 *
 | 
						|
 * Pretty print the keys to a file descriptor.
 | 
						|
 *
 | 
						|
 **/
 | 
						|
void
 | 
						|
librdf_hash_print_keys(librdf_hash* hash, FILE *fh) 
 | 
						|
{
 | 
						|
  librdf_iterator* iterator;
 | 
						|
  librdf_hash_datum *key;
 | 
						|
  
 | 
						|
  fputs("{\n", fh);
 | 
						|
 | 
						|
  key=librdf_new_hash_datum(hash->world, NULL, 0);
 | 
						|
 | 
						|
  iterator=librdf_hash_keys(hash, key);
 | 
						|
  while(!librdf_iterator_end(iterator)) {
 | 
						|
    librdf_hash_datum *k=(librdf_hash_datum *)librdf_iterator_get_key(iterator);
 | 
						|
    size_t l;
 | 
						|
    
 | 
						|
    fputs("  '", fh);
 | 
						|
    l=fwrite(k->data, k->size, 1, fh);
 | 
						|
    if(l != k->size)
 | 
						|
      break;
 | 
						|
    fputs("'\n", fh);
 | 
						|
 | 
						|
    librdf_iterator_next(iterator);
 | 
						|
  }
 | 
						|
  if(iterator)
 | 
						|
    librdf_free_iterator(iterator);
 | 
						|
 | 
						|
  librdf_free_hash_datum(key);
 | 
						|
 | 
						|
  fputc('}', fh);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_print_values:
 | 
						|
 * @hash: the hash
 | 
						|
 * @key_string: the key as a string
 | 
						|
 * @fh: file handle
 | 
						|
 *
 | 
						|
 * Pretty print the values of one key to a file descriptor.
 | 
						|
 *
 | 
						|
 **/
 | 
						|
void
 | 
						|
librdf_hash_print_values(librdf_hash* hash, const char *key_string, FILE *fh)
 | 
						|
{
 | 
						|
  librdf_hash_datum *key, *value;
 | 
						|
  librdf_iterator* iterator;
 | 
						|
  int first=1;
 | 
						|
  
 | 
						|
  key=librdf_new_hash_datum(hash->world, (char*)key_string, strlen(key_string));
 | 
						|
  if(!key)
 | 
						|
    return;
 | 
						|
  
 | 
						|
  value=librdf_new_hash_datum(hash->world, NULL, 0);
 | 
						|
  if(!value) {
 | 
						|
    key->data=NULL;
 | 
						|
    librdf_free_hash_datum(key);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  
 | 
						|
  iterator=librdf_hash_get_all(hash, key, value);
 | 
						|
  fputc('(', fh);
 | 
						|
  while(!librdf_iterator_end(iterator)) {
 | 
						|
    librdf_hash_datum *v=(librdf_hash_datum *)librdf_iterator_get_value(iterator);
 | 
						|
    size_t l;
 | 
						|
    
 | 
						|
    if(!first)
 | 
						|
      fputs(", ", fh);
 | 
						|
      
 | 
						|
    fputc('\'', fh);
 | 
						|
    l=fwrite(v->data, v->size, 1, fh);
 | 
						|
    if(l != v->size)
 | 
						|
      break;
 | 
						|
 | 
						|
    fputc('\'', fh);
 | 
						|
    first=0;
 | 
						|
    librdf_iterator_next(iterator);
 | 
						|
  }
 | 
						|
  fputc(')', fh);
 | 
						|
  librdf_free_iterator(iterator);
 | 
						|
 | 
						|
  key->data=NULL;
 | 
						|
  librdf_free_hash_datum(key);
 | 
						|
 | 
						|
  librdf_free_hash_datum(value);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* private enum */
 | 
						|
typedef enum {
 | 
						|
  HFS_PARSE_STATE_INIT = 0,
 | 
						|
  HFS_PARSE_STATE_KEY = 1,
 | 
						|
  HFS_PARSE_STATE_SEP = 2,
 | 
						|
  HFS_PARSE_STATE_EQ = 3,
 | 
						|
  HFS_PARSE_STATE_VALUE = 4
 | 
						|
} librdf_hfs_parse_state;
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_from_string:
 | 
						|
 * @hash: hash object
 | 
						|
 * @string: hash encoded as a string
 | 
						|
 *
 | 
						|
 * Initialise a hash from a string.
 | 
						|
 * 
 | 
						|
 * The string format is something like:
 | 
						|
 * key1='value1',key2='value2', key3='\'quoted value\''
 | 
						|
 *
 | 
						|
 * The 's are required and whitespace can appear around the = and ,s
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_from_string(librdf_hash* hash, const char *string) 
 | 
						|
{
 | 
						|
  const char * p;
 | 
						|
  librdf_hash_datum hd_key, hd_value; /* on stack */
 | 
						|
  const char *key;
 | 
						|
  size_t key_len;
 | 
						|
  const char *value;
 | 
						|
  size_t value_len;
 | 
						|
  int backslashes;
 | 
						|
  int saw_backslash;
 | 
						|
  librdf_hfs_parse_state state;
 | 
						|
  int real_value_len;
 | 
						|
  char *new_value;
 | 
						|
  int i;
 | 
						|
  char *to;
 | 
						|
 | 
						|
  if(!string)
 | 
						|
    return 0;
 | 
						|
  
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
  LIBRDF_DEBUG2("Parsing >>%s<<\n", string);
 | 
						|
#endif
 | 
						|
 | 
						|
  p=string;
 | 
						|
  key=NULL; key_len=0;
 | 
						|
  value=NULL; value_len=0;
 | 
						|
  backslashes=0;
 | 
						|
  state=HFS_PARSE_STATE_INIT;
 | 
						|
  while(*p) {
 | 
						|
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
    LIBRDF_DEBUG3("state %d at %s\n", state, p);
 | 
						|
#endif
 | 
						|
 | 
						|
    switch(state){
 | 
						|
      /* start of config - before key */
 | 
						|
      case HFS_PARSE_STATE_INIT:
 | 
						|
        while(*p && (isspace((int)*p) || *p == ','))
 | 
						|
          p++;
 | 
						|
        if(!*p)
 | 
						|
          break;
 | 
						|
 | 
						|
        /* fall through to next state */
 | 
						|
        state=HFS_PARSE_STATE_KEY;
 | 
						|
        
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
    LIBRDF_DEBUG3("state %d at %s\n", state, p);
 | 
						|
#endif
 | 
						|
 | 
						|
        /* start of key */
 | 
						|
      case HFS_PARSE_STATE_KEY:
 | 
						|
        key=p;
 | 
						|
        while(*p && (isalnum((int)*p) || *p == '_' || *p == '-'))
 | 
						|
          p++;
 | 
						|
        if(!*p)
 | 
						|
          break;
 | 
						|
        key_len=p-key;
 | 
						|
        
 | 
						|
        /* if 1st char is not space or alpha, move on */
 | 
						|
        if(!key_len) {
 | 
						|
          p++;
 | 
						|
          state=HFS_PARSE_STATE_INIT;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        
 | 
						|
        state=HFS_PARSE_STATE_SEP;
 | 
						|
        /* fall through to next state */
 | 
						|
      
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
    LIBRDF_DEBUG3("state %d at %s\n", state, p);
 | 
						|
#endif
 | 
						|
 | 
						|
        /* got key, now skipping spaces */
 | 
						|
      case HFS_PARSE_STATE_SEP:
 | 
						|
        while(*p && isspace((int)*p))
 | 
						|
          p++;
 | 
						|
        if(!*p)
 | 
						|
          break;
 | 
						|
        /* expecting = now */
 | 
						|
        if(*p != '=') {
 | 
						|
          p++;
 | 
						|
          state=HFS_PARSE_STATE_INIT;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        p++;
 | 
						|
        state=HFS_PARSE_STATE_EQ;
 | 
						|
        /* fall through to next state */
 | 
						|
        
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
    LIBRDF_DEBUG3("state %d at %s\n", state, p);
 | 
						|
#endif
 | 
						|
 | 
						|
        /* got key\s+= now skipping spaces " */
 | 
						|
      case HFS_PARSE_STATE_EQ:
 | 
						|
        while(*p && isspace((int)*p))
 | 
						|
          p++;
 | 
						|
        if(!*p)
 | 
						|
          break;
 | 
						|
        /* expecting ' now */
 | 
						|
        if(*p != '\'') {
 | 
						|
          p++;
 | 
						|
          state=HFS_PARSE_STATE_INIT;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        p++;
 | 
						|
        state=HFS_PARSE_STATE_VALUE;
 | 
						|
        /* fall through to next state */
 | 
						|
        
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
    LIBRDF_DEBUG3("state %d at %s\n", state, p);
 | 
						|
#endif
 | 
						|
 | 
						|
        /* got key\s+=\s+" now reading value */
 | 
						|
      case HFS_PARSE_STATE_VALUE:
 | 
						|
        value=p;
 | 
						|
        backslashes=0;
 | 
						|
        saw_backslash=0;
 | 
						|
        while(*p) {
 | 
						|
          if(!saw_backslash && *p == '\\') {
 | 
						|
            /* backslashes are removed during value copy later */
 | 
						|
            backslashes++; /* reduces real length */
 | 
						|
            saw_backslash=1;
 | 
						|
          } else {
 | 
						|
            if (!saw_backslash && *p == '\'')
 | 
						|
              break;
 | 
						|
            saw_backslash=0;
 | 
						|
          }
 | 
						|
          
 | 
						|
          p++;
 | 
						|
        }
 | 
						|
        if(!*p)
 | 
						|
          return 1;
 | 
						|
        
 | 
						|
        /* ' at end of value found */
 | 
						|
        value_len=p-value;
 | 
						|
        real_value_len=value_len-backslashes;
 | 
						|
        new_value=(char*)LIBRDF_MALLOC(cstring, real_value_len+1);
 | 
						|
        if(!new_value)
 | 
						|
          return 1;
 | 
						|
        for(i=0, to=new_value; i<(int)value_len; i++){
 | 
						|
          if(value[i]=='\\')
 | 
						|
            i++;
 | 
						|
          *to++=value[i];
 | 
						|
        }
 | 
						|
        *to='\0';
 | 
						|
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
        LIBRDF_DEBUG3("decoded key >>%s<< (true) value >>%s<<\n", key, new_value);
 | 
						|
#endif
 | 
						|
        
 | 
						|
        hd_key.data=(void*)key; hd_key.size=key_len;
 | 
						|
        hd_value.data=(void*)new_value; hd_value.size=real_value_len;
 | 
						|
        
 | 
						|
        librdf_hash_put(hash, &hd_key, &hd_value);
 | 
						|
        
 | 
						|
        LIBRDF_FREE(cstring, new_value);
 | 
						|
        
 | 
						|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
 | 
						|
        LIBRDF_DEBUG1("after decoding ");
 | 
						|
        librdf_hash_print (hash, stderr) ;
 | 
						|
        fputc('\n', stderr);
 | 
						|
#endif
 | 
						|
        state=HFS_PARSE_STATE_INIT;
 | 
						|
        p++;
 | 
						|
 | 
						|
        break;
 | 
						|
        
 | 
						|
      default:
 | 
						|
        librdf_log(hash->world, 
 | 
						|
                   0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
 | 
						|
                   "No such state %d", state);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_from_array_of_strings:
 | 
						|
 * @hash: hash object
 | 
						|
 * @array: address of the start of the array of char* pointers
 | 
						|
 *
 | 
						|
 * Initialise a hash from an array of strings.
 | 
						|
 * 
 | 
						|
 * Return value:  non 0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_from_array_of_strings(librdf_hash* hash, const char **array)
 | 
						|
{
 | 
						|
  librdf_hash_datum key, value; /* on stack */
 | 
						|
  int i;
 | 
						|
  
 | 
						|
  for(i=0; (key.data=(char*)array[i]); i+=2) {
 | 
						|
    value.data=(char*)array[i+1];
 | 
						|
    if(!value.data) {
 | 
						|
      librdf_log(hash->world, 
 | 
						|
                 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
 | 
						|
                 "Array contains an odd number of strings - %d", i);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    key.size=strlen((char*)key.data);
 | 
						|
    value.size=strlen((char*)value.data);
 | 
						|
    librdf_hash_put(hash, &key, &value);
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_get_as_boolean:
 | 
						|
 * @hash: #librdf_hash object
 | 
						|
 * @key: key string to look up
 | 
						|
 *
 | 
						|
 * Lookup a hash key and decode value as a boolean.
 | 
						|
 * 
 | 
						|
 * Return value: >0 (for true), 0 (for false) or <0 (for key not found or not known boolean value)
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_get_as_boolean (librdf_hash* hash, const char *key) 
 | 
						|
{
 | 
						|
  int bvalue= (-1);
 | 
						|
  char *value;
 | 
						|
 | 
						|
  value=librdf_hash_get(hash, key);
 | 
						|
  if(!value)
 | 
						|
    /* does not exist - fail */
 | 
						|
    return -1;
 | 
						|
 | 
						|
  switch(strlen(value)) {
 | 
						|
  case 2: /* try 'no' */
 | 
						|
    if(*value=='n' && value[1]=='o')
 | 
						|
      bvalue=0;
 | 
						|
    break;
 | 
						|
  case 3: /* try 'yes' */
 | 
						|
    if(*value=='y' && value[1]=='e' && value[2]=='s')
 | 
						|
      bvalue=1;
 | 
						|
    break;
 | 
						|
  case 4: /* try 'true' */
 | 
						|
    if(*value=='t' && value[1]=='r' && value[2]=='u' && value[3]=='e')
 | 
						|
      bvalue=1;
 | 
						|
    break;
 | 
						|
  case 5: /* try 'false' */
 | 
						|
    if(!strncmp(value, "false", 5))
 | 
						|
      bvalue=1;
 | 
						|
    break;
 | 
						|
  /* no need for default, bvalue is set above */
 | 
						|
  }
 | 
						|
 | 
						|
  LIBRDF_FREE(cstring, value);
 | 
						|
 | 
						|
  return bvalue;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_get_as_long:
 | 
						|
 * @hash: #librdf_hash object
 | 
						|
 * @key: key string to look up
 | 
						|
 *
 | 
						|
 * Lookup a hash key and decode value as a long.
 | 
						|
 * 
 | 
						|
 * Return value: >0 (for success), <0 (for key not found or not known boolean value)
 | 
						|
 **/
 | 
						|
long
 | 
						|
librdf_hash_get_as_long (librdf_hash* hash, const char *key) 
 | 
						|
{
 | 
						|
  int lvalue;
 | 
						|
  char *value;
 | 
						|
  char *end_ptr;
 | 
						|
  
 | 
						|
  value=librdf_hash_get(hash, key);
 | 
						|
  if(!value)
 | 
						|
    /* does not exist - fail */
 | 
						|
    return -1;
 | 
						|
 | 
						|
  /* Using special base 0 which allows decimal, hex and octal */
 | 
						|
  lvalue=strtol(value, &end_ptr, 0);
 | 
						|
 | 
						|
  /* nothing found, return error */
 | 
						|
  if(end_ptr == value)
 | 
						|
    lvalue= (-1);
 | 
						|
 | 
						|
  LIBRDF_FREE(cstring, value);
 | 
						|
  return lvalue;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_put_strings:
 | 
						|
 * @hash: hash object
 | 
						|
 * @key: key 
 | 
						|
 * @value: value
 | 
						|
 *
 | 
						|
 * Insert key/value pairs into the hash as strings.
 | 
						|
 * 
 | 
						|
 * The key and values are copied into the hash, no sharing i s done.
 | 
						|
 * 
 | 
						|
 * Return value: non 0 on failure
 | 
						|
 **/
 | 
						|
int
 | 
						|
librdf_hash_put_strings(librdf_hash* hash, const char *key, const char *value)
 | 
						|
{
 | 
						|
  librdf_hash_datum key_hd; /* static */
 | 
						|
  librdf_hash_datum value_hd;
 | 
						|
 | 
						|
  /* Note: We do not have to init the world field of
 | 
						|
   * these librdf_hash_datum since they are never put on the
 | 
						|
   * hash datums free list
 | 
						|
   */
 | 
						|
 | 
						|
  key_hd.data=(void*)key;
 | 
						|
  key_hd.size=strlen(key);
 | 
						|
  value_hd.data=(void*)value;
 | 
						|
  value_hd.size=strlen(value);
 | 
						|
  return librdf_hash_put(hash, &key_hd, &value_hd);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_hash_interpret_template:
 | 
						|
 * @template_string: template string to interprate
 | 
						|
 * @dictionary: dictionary of key/values to substitute
 | 
						|
 * @prefix: prefix to mark a key in the template
 | 
						|
 * @suffix: suffix to mark a key in the template
 | 
						|
 * 
 | 
						|
 * Interpret keys in a template string to their value in a dictionary.
 | 
						|
 * 
 | 
						|
 * Can be used to do variable substitution for a string where
 | 
						|
 * the syntax that marks the variable is defined by the @prefix
 | 
						|
 * and @suffix strings, and the variables are stored in the @dictionary
 | 
						|
 * hash table.
 | 
						|
 *
 | 
						|
 * Return value: Newly allocated string, or NULL on failure
 | 
						|
 **/
 | 
						|
unsigned char*
 | 
						|
librdf_hash_interpret_template(const unsigned char* template_string,
 | 
						|
                               librdf_hash* dictionary,
 | 
						|
                               const unsigned char* prefix, 
 | 
						|
                               const unsigned char* suffix) 
 | 
						|
{
 | 
						|
  raptor_stringbuffer* sb;
 | 
						|
  unsigned char* result=NULL;
 | 
						|
  size_t len;
 | 
						|
  size_t prefix_len=strlen((const char*)prefix);
 | 
						|
  size_t suffix_len=strlen((const char*)suffix);
 | 
						|
  
 | 
						|
  sb=raptor_new_stringbuffer();
 | 
						|
  if(!sb)
 | 
						|
    return NULL;
 | 
						|
  
 | 
						|
  len=strlen((const char*)template_string);
 | 
						|
  
 | 
						|
  while(*template_string) {
 | 
						|
    unsigned char* p;
 | 
						|
    unsigned char* s;
 | 
						|
    librdf_hash_datum key; /* static */
 | 
						|
    librdf_hash_datum *hd_value;
 | 
						|
    size_t len2;
 | 
						|
    
 | 
						|
    p=(unsigned char*)strstr((const char*)template_string, (const char*)prefix);
 | 
						|
    if(!p) {
 | 
						|
      /* No more prefixes found so append rest of template */
 | 
						|
      raptor_stringbuffer_append_counted_string(sb, template_string, len, 1);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    len2=p-template_string;
 | 
						|
    if(len2)
 | 
						|
      raptor_stringbuffer_append_counted_string(sb, template_string, len2, 1);
 | 
						|
 | 
						|
    template_string += len2 + prefix_len;  len -= len2 + prefix_len;
 | 
						|
    
 | 
						|
    /* key starts here */
 | 
						|
    key.data=(void*)template_string;
 | 
						|
    
 | 
						|
    s=(unsigned char*)strstr((const char*)template_string, (const char*)suffix);
 | 
						|
    if(!s)
 | 
						|
      /* template ended without a closing key suffix so just give up */
 | 
						|
      break;
 | 
						|
 | 
						|
    /* now have key */
 | 
						|
    len2= s - (unsigned char*)key.data;
 | 
						|
    key.size= len2;
 | 
						|
 | 
						|
    /* move past key and suffix */
 | 
						|
    template_string += len2 + suffix_len;  len -= len2 + suffix_len;
 | 
						|
 | 
						|
    hd_value=librdf_hash_get_one(dictionary, &key);
 | 
						|
    /* append value if there is one */
 | 
						|
    if(hd_value) {
 | 
						|
      raptor_stringbuffer_append_counted_string(sb,
 | 
						|
                                                (const unsigned char*)hd_value->data, 
 | 
						|
                                                hd_value->size, 1);
 | 
						|
      librdf_free_hash_datum(hd_value);
 | 
						|
    }
 | 
						|
    
 | 
						|
  }
 | 
						|
 | 
						|
  /* Generate a string result */
 | 
						|
  len=raptor_stringbuffer_length(sb);
 | 
						|
  if(len) {
 | 
						|
    result=(unsigned char*)LIBRDF_MALLOC(cstring, len+1);
 | 
						|
    raptor_stringbuffer_copy_to_string(sb, result, len);
 | 
						|
  }
 | 
						|
  
 | 
						|
  raptor_free_stringbuffer(sb);
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/* TEST CODE */
 | 
						|
 | 
						|
 | 
						|
#ifdef STANDALONE
 | 
						|
 | 
						|
/* one more prototype */
 | 
						|
int main(int argc, char *argv[]);
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
main(int argc, char *argv[]) 
 | 
						|
{
 | 
						|
  librdf_hash *h, *h2, *ch;
 | 
						|
  const char *test_hash_types[]={"bdb", "memory", NULL};
 | 
						|
  const char *test_hash_values[]={"colour","yellow", /* Made in UK, can you guess? */
 | 
						|
			    "age", "new",
 | 
						|
			    "size", "large",
 | 
						|
                            "colour", "green",
 | 
						|
			    "fruit", "banana",
 | 
						|
                            "colour", "yellow",
 | 
						|
			    NULL, NULL};
 | 
						|
  const char *test_duplicate_key="colour";
 | 
						|
  const char *test_hash_array[]={"shape", "cube",
 | 
						|
                                 "sides", "6", /* for testing get as long */
 | 
						|
                                 "3d", "yes", /* testing bool */
 | 
						|
                                 "colours", "red",
 | 
						|
                                 "colours", "yellow",
 | 
						|
                                 "creator", "rubik",
 | 
						|
                                 NULL};
 | 
						|
  const char * const test_hash_string="field1='value1', field2='\\'value2', field3='\\\\', field4='\\\\\\'', field5 = 'a' ";
 | 
						|
  const char *test_hash_delete_key="size";
 | 
						|
  const unsigned char* template_string=(const unsigned char*)"the shape is %{shape} and the sides are %{sides} created by %{rubik}";
 | 
						|
  const unsigned char* template_expected=(const unsigned char*)"the shape is cube and the sides are 6 created by ";
 | 
						|
  int i,j;
 | 
						|
  const char *type;
 | 
						|
  librdf_hash_datum hd_key, hd_value; /* on stack */
 | 
						|
  const char *program=librdf_basename((const char*)argv[0]);
 | 
						|
  int b;
 | 
						|
  long l;
 | 
						|
  unsigned char* template_result;
 | 
						|
  librdf_world *world;
 | 
						|
  
 | 
						|
  world=librdf_new_world();
 | 
						|
  librdf_world_open(world);
 | 
						|
  
 | 
						|
  if(argc ==2) {
 | 
						|
    type=argv[1];
 | 
						|
    h=librdf_new_hash(world, NULL);
 | 
						|
    if(!h) {
 | 
						|
      fprintf(stderr, "%s: Failed to create new hash type '%s'\n",
 | 
						|
	      program, type);
 | 
						|
      return(0);
 | 
						|
    }
 | 
						|
    
 | 
						|
    librdf_hash_open(h, "test", 0644, 1, 1, NULL);
 | 
						|
    librdf_hash_from_string(h, argv[1]);
 | 
						|
    fprintf(stdout, "%s: resulting ", program);
 | 
						|
    librdf_hash_print(h, stdout);
 | 
						|
    fputc('\n', stdout);
 | 
						|
    fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h));
 | 
						|
    librdf_hash_close(h);
 | 
						|
    librdf_free_hash(h);
 | 
						|
    return(0);
 | 
						|
  }
 | 
						|
  
 | 
						|
  
 | 
						|
  for(i=0; (type=test_hash_types[i]); i++) {
 | 
						|
    fprintf(stdout, "%s: Trying to create new %s hash\n", program, type);
 | 
						|
    h=librdf_new_hash(world, type);
 | 
						|
    if(!h) {
 | 
						|
      fprintf(stderr, "%s: Failed to create new hash type '%s'\n", program, type);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if(librdf_hash_open(h, "test", 0644, 1, 1, NULL)) {
 | 
						|
      fprintf(stderr, "%s: Failed to open new hash type '%s'\n", program, type);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    
 | 
						|
    
 | 
						|
    for(j=0; test_hash_values[j]; j+=2) {
 | 
						|
      hd_key.data=(char*)test_hash_values[j];
 | 
						|
      hd_value.data=(char*)test_hash_values[j+1];
 | 
						|
      fprintf(stdout, "%s: Adding key/value pair: %s=%s\n", program,
 | 
						|
	      (char*)hd_key.data, (char*)hd_value.data);
 | 
						|
      
 | 
						|
      hd_key.size=strlen((char*)hd_key.data);
 | 
						|
      hd_value.size=strlen((char*)hd_value.data); 
 | 
						|
      librdf_hash_put(h, &hd_key, &hd_value);
 | 
						|
      
 | 
						|
      fprintf(stdout, "%s: resulting ", program);
 | 
						|
      librdf_hash_print(h, stdout);
 | 
						|
      fputc('\n', stdout);
 | 
						|
      fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h));
 | 
						|
    }
 | 
						|
    
 | 
						|
    fprintf(stdout, "%s: Deleting key '%s'\n", program, test_hash_delete_key);
 | 
						|
    hd_key.data=(char*)test_hash_delete_key;
 | 
						|
    hd_key.size=strlen((char*)hd_key.data);
 | 
						|
    librdf_hash_delete_all(h, &hd_key);
 | 
						|
    
 | 
						|
    fprintf(stdout, "%s: resulting ", program);
 | 
						|
    librdf_hash_print(h, stdout);
 | 
						|
    fputc('\n', stdout);
 | 
						|
    fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h));
 | 
						|
    
 | 
						|
    fprintf(stdout, "%s: resulting %s hash keys: ", program, type);
 | 
						|
    librdf_hash_print_keys(h, stdout);
 | 
						|
    fputc('\n', stdout);
 | 
						|
 | 
						|
    fprintf(stdout, "%s: all values of key '%s'=", program, test_duplicate_key);
 | 
						|
    librdf_hash_print_values(h, test_duplicate_key, stdout);
 | 
						|
    fputc('\n', stdout);
 | 
						|
 | 
						|
    fprintf(stdout, "%s: cloning %s hash\n", program, type);
 | 
						|
    ch=librdf_new_hash_from_hash(h);
 | 
						|
    if(ch) {
 | 
						|
      fprintf(stdout, "%s: resulting cloned ", program);
 | 
						|
      librdf_hash_print(ch, stdout);
 | 
						|
      fputc('\n', stdout);
 | 
						|
      fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(ch));
 | 
						|
      
 | 
						|
      librdf_hash_close(ch);
 | 
						|
      librdf_free_hash(ch);
 | 
						|
    } else {
 | 
						|
      fprintf(stderr, "%s: Failed to clone %s hash\n", program, type);
 | 
						|
    }
 | 
						|
 | 
						|
    librdf_hash_close(h);
 | 
						|
      
 | 
						|
    fprintf(stdout, "%s: Freeing hash\n", program);
 | 
						|
    librdf_free_hash(h);
 | 
						|
  }
 | 
						|
  fprintf(stdout, "%s: Getting default hash factory\n", program);
 | 
						|
  h2=librdf_new_hash(world, NULL);
 | 
						|
  if(!h2) {
 | 
						|
    fprintf(stderr, "%s: Failed to create new hash from default factory\n", program);
 | 
						|
    return(1);
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf(stdout, "%s: Initialising hash from array of strings\n", program);
 | 
						|
  if(librdf_hash_from_array_of_strings(h2, test_hash_array)) {
 | 
						|
    fprintf(stderr, "%s: Failed to init hash from array of strings\n", program);
 | 
						|
    return(1);
 | 
						|
  }
 | 
						|
  
 | 
						|
  fprintf(stdout, "%s: resulting hash ", program);
 | 
						|
  librdf_hash_print(h2, stdout);
 | 
						|
  fputc('\n', stdout);
 | 
						|
  fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h2));
 | 
						|
 | 
						|
  fprintf(stdout, "%s: resulting hash keys: ", program);
 | 
						|
  librdf_hash_print_keys(h2, stdout);
 | 
						|
  fputc('\n', stdout);
 | 
						|
 | 
						|
  
 | 
						|
  /* test get as boolean and long functions */
 | 
						|
  {
 | 
						|
    librdf_iterator* iterator;
 | 
						|
    librdf_hash_datum *key_hd;
 | 
						|
    
 | 
						|
    key_hd=librdf_new_hash_datum(world, NULL, 0);
 | 
						|
    
 | 
						|
    iterator=librdf_hash_keys(h2, key_hd);
 | 
						|
    while(!librdf_iterator_end(iterator)) {
 | 
						|
      librdf_hash_datum *k=(librdf_hash_datum*)librdf_iterator_get_key(iterator);
 | 
						|
      char *key_string;
 | 
						|
      
 | 
						|
      key_string=(char*)LIBRDF_MALLOC(cstring, k->size+1);
 | 
						|
      if(!key_string)
 | 
						|
        break;
 | 
						|
      strncpy(key_string, (char*)k->data, k->size);
 | 
						|
      key_string[k->size]='\0';
 | 
						|
      
 | 
						|
      fprintf(stdout, "%s: boolean value of key '%s' is ", program,
 | 
						|
              key_string);
 | 
						|
      b=librdf_hash_get_as_boolean(h2, key_string);
 | 
						|
      fprintf(stdout, "%d (0 F, -1 Bad, else T)\n", b);
 | 
						|
      
 | 
						|
      fprintf(stdout, "%s: long value of key '%s' is ", program,
 | 
						|
              key_string);
 | 
						|
      l=librdf_hash_get_as_long(h2, key_string);
 | 
						|
      fprintf(stdout, "%ld (decimal, -1 Bad)\n", l);
 | 
						|
      
 | 
						|
      LIBRDF_FREE(cstring, key_string);
 | 
						|
      librdf_iterator_next(iterator);
 | 
						|
    }
 | 
						|
    if(iterator)
 | 
						|
      librdf_free_iterator(iterator);
 | 
						|
    
 | 
						|
    librdf_free_hash_datum(key_hd);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  fprintf(stdout, "%s: Freeing hash\n", program);
 | 
						|
  /* close() done automatically by free so not required */
 | 
						|
  /* librdf_hash_close(h2); */
 | 
						|
  librdf_free_hash(h2);
 | 
						|
 | 
						|
  h2=librdf_new_hash(world, NULL);
 | 
						|
  fprintf(stdout, "%s: Initialising hash from string >>%s<<\n", program, 
 | 
						|
          test_hash_string);
 | 
						|
  librdf_hash_from_string (h2, test_hash_string);
 | 
						|
  fprintf(stdout, "%s: resulting ", program);
 | 
						|
  librdf_hash_print(h2, stdout);
 | 
						|
  fputc('\n', stdout);
 | 
						|
  fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h2));
 | 
						|
 | 
						|
  librdf_free_hash(h2);
 | 
						|
 | 
						|
   
 | 
						|
  fprintf(stdout, "%s: Subtituting into template >>%s<<\n", program, 
 | 
						|
          template_string);
 | 
						|
  h2=librdf_new_hash(world, NULL);
 | 
						|
  librdf_hash_from_array_of_strings(h2, test_hash_array);
 | 
						|
 | 
						|
  template_result=librdf_hash_interpret_template(template_string, h2, 
 | 
						|
                                                 (const unsigned char*)"%{", 
 | 
						|
                                                 (const unsigned char*)"}");
 | 
						|
  if(strcmp((const char*)template_result, (const char*)template_expected)) {
 | 
						|
    fprintf(stdout, "%s: Templating failed. Result was >>%s<< but expected >>%s<<\n", program, 
 | 
						|
            template_result, template_expected);
 | 
						|
    exit(1);
 | 
						|
  } else
 | 
						|
    fprintf(stdout, "%s: resulting in >>%s<<\n", program, template_result);
 | 
						|
 | 
						|
  LIBRDF_FREE(cstring, template_result);
 | 
						|
 | 
						|
  librdf_free_hash(h2);
 | 
						|
 | 
						|
   
 | 
						|
  librdf_free_world(world);
 | 
						|
  
 | 
						|
  /* keep gcc -Wall happy */
 | 
						|
  return(0);
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |