/*
 * (c) Copyright 1993 by Panagiotis Tsirigotis
 * All rights reserved.  The file named COPYRIGHT specifies the terms 
 * and conditions for redistribution.
 */

static char RCSid[] = "$Id: dict.c,v 3.3 93/11/14 22:24:54 panos Exp $" ;
static char version[] = VERSION ;

#include "dictimpl.h"

int dict_errno ;

struct name_value
{
	int nv_value ;
	char *nv_name ;
} ;


static struct name_value error_codes[] =
	{
		{	DICT_ENOMEM,			"out of memory"											},
		{	DICT_ENOTFOUND,		"object not found"										},
		{	DICT_ENOOOCOMP,		"object-object comparison function is missing"	},
		{	DICT_ENOKOCOMP,		"key-object comparison function is missing"		},
		{	DICT_ENULLOBJECT,		"object is NULL"											},
		{	DICT_EEXISTS,			"object exists"											},
		{	DICT_ENOHVFUNC,		"hashvalue extraction function is missing"		},
		{	DICT_EBADOBJECT,		"object does not exist"									},
		{	DICT_EBADORDER,		"bad order flag"											},
		{	DICT_EORDER,			"specified order not supported"						},
		{	DICT_ENOERROR,			NULL															}
	} ;


void __dict_terminate( prefix, msg )
	char *prefix ;
	char *msg ;
{
	static char buf[ 80 ] ;
	char *strcat() ;
	char *strcpy() ;

	(void) strcpy( buf, "DICT " ) ;
	(void) strcat( buf, prefix ) ;
	(void) strcat( buf, ": " ) ;
	(void) strcat( buf, msg ) ;
	(void) strcat( buf, "\n" ) ;
	(void) write( 2, buf, strlen( buf ) ) ;
	abort() ;
	_exit( 1 ) ;
	/* NOTREACHED */
}


void __dict_fatal_error( caller, error_code )
	char			*caller ;
	int			error_code ;
{
	struct name_value *nvp ;
	char *msg ;

	/*
	 * Lookup error message
	 */
	msg = "unknown error" ;
	for ( nvp = error_codes ; nvp->nv_name ; nvp++ )
		if ( nvp->nv_value == error_code )
		{
			msg = nvp->nv_name ;
			break ;
		}
	__dict_terminate( caller, msg ) ;
}


dict_h __dict_create_error( caller, flags, errp, error_code )
	char	*caller ;
	int	flags ;
	int	*errp ;
	int	error_code ;
{
	dheader_s dh ;

	dh.flags = flags ;
	dh.errnop = ( errp == INT_NULL ) ? &dict_errno : errp ;
	HANDLE_ERROR( &dh, caller, error_code, NULL_HANDLE ) ;
	/* NOTREACHED */
}


int __dict_args_ok( caller, flags, errp, oo_comp, ko_comp, allowed_orders )
	char				*caller ;
	int				flags ;
	int				*errp ;
	dict_function	oo_comp ;
	dict_function	ko_comp ;
	int				allowed_orders ;
{
	int requested_order ;

	if ( BAD_ORDER( flags ) )
	{
		(void) __dict_create_error( caller, flags, errp, DICT_EBADORDER ) ;
		return( FALSE ) ;
	}

	/*
	 * If the user provided an object-object comparator, we can pretend
	 * that the library supports the DICT_UNORDERED flag.
	 */
	if ( oo_comp )
		allowed_orders |= DICT_UNORDERED ;

	requested_order = ( flags & ORDER_FLAGS ) ;
	if ( requested_order && ! ( allowed_orders & requested_order ) )
	{
		(void) __dict_create_error( caller, flags, errp, DICT_EORDER ) ;
		return( FALSE ) ;
	}

	/*
	 * An object-object comparator is required if
	 *		order is requested,
	 * or
	 *		key uniqueness is requested
	 * or
	 *		the library requires it.
	 */
	if ( oo_comp == NULL_FUNC && ( flags & (DICT_ORDERED | DICT_UNIQUE_KEYS) ) )
	{
		(void) __dict_create_error( caller, flags, errp, DICT_ENOOOCOMP ) ;
		return( FALSE ) ;
	}

#ifdef notdef
	if ( ko_comp == NULL )
	{
		(void) __dict_create_error( caller, flags, errp, DICT_ENOKOCOMP ) ;
		return( FALSE ) ;
	}
#endif

	return( TRUE ) ;
}


void __dict_init_header( dhp, oo_comp, ko_comp, flags, errnop )
	dheader_s *dhp ;
	dict_function oo_comp, ko_comp ;
	int flags, *errnop ;
{
	dhp->oo_comp = oo_comp ;
	dhp->ko_comp = ko_comp ;
	dhp->flags = flags ;
	dhp->errnop = ( errnop == INT_NULL ) ? &dict_errno : errnop ;
}

