/*
 * Copyright 2005-2015 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 *
 * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
 * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
 */

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

#define SIZE 	((int)4097)

typedef struct hashrec {
	struct hashrec  *next;
	char   *name;
	int    cnt;
} hashrec;

static hashrec *table[SIZE] = { 
	NULL, };


static int hash(const char *name)
{
	int n = 0;

	while(*name)
		n +=  (*name++ - 'A') + (n << 5);

#ifdef CRAY
	if(n<0) n = -n;
#else
	if(n<0)  {
		int m = -n/SIZE;
		n += (m+1)*SIZE;
	}
#endif
	return n % SIZE;
}

void hash_stat()
{
	int i;
	int a=0,b=0,c=0;
	hashrec *h;

	printf("Table size is %d. ",SIZE);

	for(i=0;i<SIZE;i++)
		if(h = table[i])
		{
			a++;
			while(h) { b++; c += h->cnt; h = h->next; };
		}

	printf("Used: %d, Total: %d, Strings: %d\n",a,b,c);
}

char *strcache(const char *name)
{
	hashrec *h;
	int      n;

	if(name == NULL) return NULL;

	n = hash(name);
	h = table[n];

	while(h)
	{
		if(EQ(h->name,name))
		{
			h->cnt++;
			return h->name;
		}
		h = h->next;
	}

	h        = NEW(hashrec);
	h->name  = NEW_STRING(name);
	h->next  = table[n];
	h->cnt   = 1;
	table[n] = h;

	return h->name;
}

void strfree(char *name)
{

	hashrec *h;
	hashrec *p = NULL;
	int      n;

	if(name == NULL) return;

	n = hash(name);
	h = table[n];

	while(h)
	{
		if(h->name == name)
		{
			h->cnt--;
			break;
		}
		p = h;
		h = h->next;
	}

	if(h == NULL)
	{
		marslog(LOG_WARN,"%s was not in hash table",name);
		abort();
		printf("n=%d\n",n);
		h = table[n];
		while(h)
		{
			printf("%s %d\n",h->name,h->cnt);
			h = h->next;
		}
		return;
	}

	if(h->cnt == 0)
	{
		if(p) p->next = h->next;
		else table[n] = h->next;
		FREE(h->name);
		FREE(h);
	}
}


