/*
Copyright (C) 1997 by Warren R. Gish.  All Rights Reserved.
*/
#include <ncbi.h>
#include <gish.h>
#include <gishlib.h>
#include "nrdb.h"

SeqNamePtr
SeqName_New()
{
	SeqNamePtr	snp;
	snp = (SeqNamePtr)ckalloc0(sizeof(SeqName));
	return snp;
}


SeqNamePtr
SeqName_Dup(old)
	SeqNamePtr	old;
{
	register SeqNamePtr	new;

	if (old == NULL)
		return NULL;
	new = SeqName_New();
	new->nrfp = old->nrfp;
	if (old->name == NULL) {
		new->name = NULL;
		new->namelen = 0;
	}
	else {
		new->namelen = old->namelen;
		new->name = my_dup(old->name, old->namelen+1);
	}
	return new;
}


SeqNamePtr
SeqStr_Name(ssp)
	SeqStrPtr	ssp;
{
	return ssp->name1;
}


SeqStrPtr
SeqStr_New()
{
	register SeqStrPtr	ssp;

	ssp = (SeqStrPtr)ckalloc0(sizeof(SeqStr));
	return ssp;
}


SeqStrPtr
SeqStr_Dup(old)
	SeqStrPtr	old;
{
	SeqStrPtr	new;
	size_t	len;

	new = SeqStr_New();
	new->name1 = SeqName_Dup(old->name1);
	new->id = old->id;
	hashray[new->id].sp = new;
	if (old->seq == NULL) {
		new->seq = NULL;
		new->seqlen = 0;
		new->clen = 0;
		new->compression = 0;
	}
	else {
		new->seqlen = old->seqlen;
		new->clen = old->clen;
		new->compression = old->compression;
		len = (old->clen ? old->clen : old->seqlen + 1);
		new->seq = my_dup(old->seq, len);
	}
	return new;
}

int
SeqStr_Cmp(id1, id2)
	unsigned long	id1, id2;
{
	register char *cp1, *cp2, ch;

	if (hashray[id1].hashval == hashray[id2].hashval) {
		SeqStrPtr	ss1, ss2;
		++numhashhits;
		ss1 = hashray[id1].sp; ss2 = hashray[id2].sp;
		if (ss1->seqlen != ss2->seqlen)
			return -1;
		if (ss1->compression != ss2->compression)
			return -1;
		cp1 = ss1->seq, cp2 = ss2->seq;
		if (ss1->clen != 0)
			return Nlm_MemCmp(cp1, cp2, ss1->clen);
		return Nlm_MemCmp(cp1, cp2, ss1->seqlen);
	}
	return -1;
}


SeqStrPtr
SeqStr_Append(ssp)
	SeqStrPtr	ssp;
{
	SeqStrPtr	new;

	new = SeqStr_Dup(ssp);
	if (listhead == NULL)
		listhead = new;
	else
		listtail->chain = new;
	listtail = new;
	SeqStr_AddBase(new);
	return new;
}

int
SeqStr_AppendName(ssp, new)
	SeqStrPtr	ssp;
	SeqNamePtr	new;
{
	register SeqNamePtr	snp;

	snp = ssp->name1;
	while (snp->chain != NULL)
		snp = snp->chain;
	
	snp->chain = new = SeqName_Dup(new);
	new->chain = NULL;
	return 0;
}


SeqStr_InitBase()
{
	int	i;
	for (i=0; i<DIM(baseray); ++i)
		baseray[i] = ULONG_MAX;
	return 0;
}


int
SeqStr_AddBase(new)
	register SeqStrPtr	new;
{
	unsigned long	base, tmp, tmpid;

	++seqcnt;
	base = hashray[new->id].hashval & BITMASK(16);
	if (baseray[base] == ULONG_MAX) {
		baseray[base] = new->id;
		hashray[new->id].nextid = ULONG_MAX;
	}
	else {
		tmp = baseray[base];
		hashray[new->id].nextid = tmp;
		baseray[base] = new->id;
	}
	return 0;
}


SeqStrPtr
SeqStr_AlreadyFound(new)
	register SeqStrPtr	new;
{
	unsigned	base;
	register SeqStrPtr	old;
	unsigned long	oldid;

	if (new->seqlen <= 0)
		return NULL;
	base = hashray[new->id].hashval & BITMASK(16);
	oldid = baseray[base];
	if (oldid == ULONG_MAX)
		return NULL;

	++numhits;

	for (; oldid != ULONG_MAX; oldid = hashray[oldid].nextid) {
		++numtothits;
		if (SeqStr_Cmp(new->id, oldid) == 0)
			return hashray[oldid].sp;
	}
	return NULL;
}

