/*
	Attribute handling gear. Shit simple.

	Andrew Molitor, amolitor@eagle.wesleyan.edu

	1991

*/

#include "udb_defs.h"
#include	<stdio.h>

#ifdef WANT_ANSI
#ifdef __STDC__
#include <stdlib.h>
#endif /* __STDC__ */
#endif /* WANT_ANSI */

/*
	Hash function for the cache code. Stolen from mjr.
*/
/*
WARNING  - overflows ignored. no big deal
*/
unsigned int
attr_hash(key,len,width)
char    *key;   /* Pointer to the key string. */
int     len;    /* The length of said string. */
int     width;  /* Width of the hash table.   */
{
        register int h = 0;
        register int loop;
        register char *p;

#define HASH4a   h = (h << 5) - h + *p++;
#define HASH4b   h = (h << 5) + h + *p++;
#define HASH4 HASH4b

        p = key;

        if (len > 0) {
                loop = (len + 8 - 1) >> 3;

#ifndef VMS
                /* Duff's device, as hated by Vax C. */

                switch(len & (8 - 1)) {
                        case 0: do {            /* All fall throughs */
                                        HASH4;
                                case 7: HASH4;
                                case 6: HASH4;
                                case 5: HASH4;
                                case 4: HASH4;
                                case 3: HASH4;
                                case 2: HASH4;
                                case 1: HASH4;
                        } while (--loop);
                }
#else
		if (!(len & (8 - 1)))
		{
		    do {
		        HASH4;
		    } while (--loop);
		}
#endif


        }
        return(h > 0 ? h % width : (-h) % width);
}

/*
	Free an attribute.
*/

int attrfree(a)
Attr	*a;
{
	extern void deferfree();
	
	if(a && a->data)
		deferfree(a->data);
	if(a)
		deferfree((char *)a);
	return 0;
}

/*
	Routines for dealing with reading/writing attributes to disk.

	We stow attributes on disk as an int containing the size,
followed by the data proper. This means two disk hits per operation,
but there seems to be no easy way around this.

*/


Attr	*
attrfromFILE(f)
FILE	*f;
{
	Attr	*atr;

	/* Get a new attribute struct */

	if((atr = (Attr *)malloc(sizeof(Attr))) == (Attr *)0){
		return((Attr *)0);
	}

	/* Read in the size. One int. */

	fread(&(atr->size), sizeof(int), 1, f);

	/* Get a buffer big enough. */

	if((atr->data = (char *)malloc(atr->size)) == (char *)0){
		free(atr);
		return((Attr *)0);
	}

	/* Now go get the data */

	fread(atr->data, 1, atr->size, f);
	return(atr);
}


int attrtoFILE(a,f)
Attr	*a;
FILE	*f;
{
	/* Write out the size. */

	fwrite(&(a->size), sizeof(int), 1, f);

	/* Write out the data */

	fwrite(a->data, 1, a->size, f);

	return 0;
}

int attr_siz(a)
Attr	*a;
{
	return(a->size + sizeof(int));
}