identList.c 4.55 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;
}