identList.c 4.64 KB
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>

#include <expValue.h>
#include <bbtree.h>
#include <ident.h>
#include <identList.h>


struct identList
{
	s_bbTree * idIdx;
	s_bbTree * idHash;
};


/*
 * statische Funktionen (interner gebrauch)
 */
static
	int
idHashCmp (void * _a, void * _b)
{
	s_ident * a = (s_ident *) _a;
	s_ident * b = (s_ident *) _b;

	return strcmp (identGetKey (a), identGetKey (b));
}

static
	int
idIdxCmp (void * _a, void * _b)
{
	s_ident * a = (s_ident *) _a;
	s_ident * b = (s_ident *) _b;

	return identGetIdx (a) - identGetIdx (b);
}


/*
 * nicht statische Funktionen (Interface)
 */

/*
 * Contructors / Destructors for identList
 */
	s_identList *
identListNew (void)
{
	s_identList * ret = (s_identList *) malloc (sizeof (s_identList));

	ret->idIdx  = bbTreeNew (idIdxCmp);
	ret->idHash = bbTreeNew (idHashCmp);

	return ret;
}

void
identListFree (s_identList * l)
{
	s_ident ** idArray,
	        ** _run;

	for (_run = idArray = (s_ident **) identListToArray (l);
			*_run != NULL;
			_run++)
	{
		identDequeue (*_run);
		if (! identIsQueued (*_run))
			identFree (*_run);
	}
	
	free (idArray);

	bbTreeFree (l->idIdx);
	bbTreeFree (l->idHash);

	free (l);
}

/*
 * insertions or deletion into a identList
 */
	s_ident *
identListPutVal (s_identList * l, s_ident * val)
{
	s_ident * oldVal;
	int    idx	= identGetIdx (val);
	char * key	= identGetKey (val);

	identEnqueue (val);

	if ((idx < 0 && key[0] == '\0') || idx != -1 && key[0] != '\0')
		/* calling error: either key or idx must be valid. But not both. */
		return NULL;

	if (idx >= 0)
		oldVal = (s_ident *) bbTreeInsert (l->idIdx, val);
	else
		oldVal = (s_ident *) bbTreeInsert (l->idHash, val);

	if (oldVal != NULL)
	/* 
	 * these are few lines with a lot behind them. The not obvious question 
	 * here is: What happens if oldval points to the same address than val?
	 * well, this could only happen if val was was formally queued, because
	 * else oldVal would be NULL. Knowing this makes clear that the queue
	 * state is not changed at all, because first it was increased above with
	 * identEnqueue and the it will be decreased in this if block again. But as
	 * it was formally queued it will not be freed (Good)!
	 */
	{
		identDequeue (oldVal);
		if (! identIsQueued (oldVal))
			identFree (oldVal);
	}

	return val;
}

	s_ident *
identListPutExpByIdx (s_identList * l, int idx, s_expVal * val)
{
	return identListPutVal (l, identExpNew (idx, NULL, val));
}

	s_ident *
identListPutIdlByIdx (s_identList * l, int idx, s_identList * val)
{
	return identListPutVal (l, identIdlNew (idx, NULL, val));
}

	s_ident *
identListPutExpByKey (s_identList * l, const char * key, s_expVal * val)
{
	return identListPutVal (l, identExpNew (-1, key, val));
}

	s_ident *
identListPutIdlByKey (s_identList * l, const char * key, s_identList * val)
{
	return identListPutVal (l, identIdlNew (-1, key, val));
}

	void
identListRemoveByIdx (s_identList * l, int idx)
{
	s_ident * seek = (s_ident *) identNew (idx, NULL);
	s_ident * val  = bbTreeRemove (l->idIdx, seek);

#ifdef DEBUG2
	printf ("[!DEBUG!] seek (remove) identNew: %d/%s\n", idx, "");
#endif

	identFree (seek);

	if (val != NULL)
	{
		identDequeue (val);
		if (! identIsQueued (val))
			identFree (val);
	}
}

	void
identListRemoveByKey (s_identList * l, const char * key)
{
	s_ident * seek = (s_ident *) identNew (-1, key);
	s_ident * val  = bbTreeRemove (l->idIdx, seek);

#ifdef DEBUG2
	printf ("[!DEBUG!] seek (remove) identNew: %d/%s\n", -1, key);
#endif

	identFree (seek);

	if (val != NULL)
	{
		identDequeue (val);
		if (! identIsQueued (val))
			identFree (val);
	}
}

/*
 * seeking in identList
 */
	s_ident *
identListSeekIdx (s_identList * l, int idx)
{
	s_ident * seek = (s_ident *) identNew (idx, NULL);
	s_ident * val  = (s_ident *) bbTreeSeek (l->idIdx, seek);

#ifdef DEBUG2
	printf ("[!DEBUG!] seek identNew: %d/%s\n", idx, "");
#endif

	identFree (seek);

	return val;
}

	s_ident *
identListSeekKey (s_identList * l, const char * key)
{
	s_ident * seek = (s_ident *) identNew (-1, key);
	s_ident * val  = (s_ident *) bbTreeSeek (l->idHash, seek);

#ifdef DEBUG2
	printf ("[!DEBUG!] seek identNew: %d/%s\n", -1, key);
#endif

	identFree (seek);

	return val;
}

/*
 * identList to other DataStructures 
 */
	s_ident **
identListToArray (s_identList * l)
{
	int        idIdxLen  = bbTreeSize (l->idIdx);
	int        idHashLen = bbTreeSize (l->idHash);
	int        retLen    = idIdxLen + idHashLen + 1;
	s_ident ** ret       = (s_ident **) malloc (sizeof (s_ident *) * retLen);

	memset (ret, 0, sizeof (s_ident **) * retLen);

	bbTreeInOrder (l->idIdx, (void **) ret);
	bbTreeInOrder (l->idHash, (void **) &(ret[idIdxLen]));

	return ret;
}