Blob Blame Raw

#include "private.h"


void heliPairInit(HeliPair *p) {
	p->key = p->value = NULL;
	p->freeKey = p->freeValue = NULL;
}

void heliPairDestroy(HeliPair *p) {
	if (p->key && p->freeKey) p->freeKey(p->key);
	if (p->value && p->freeValue) p->freeKey(p->value);
	heliPairInit(p);
}

void heliArrayInit(HeliArray *a) {
	a->items = NULL;
	a->count = a->allocated = 0;
}

void heliArrayDestroy(HeliArray *a) {
	heliArrayClear(a);
	free(a->items);
	heliArrayInit(a);
}

HeliPair* heliArrayGet(HeliArray *a, int i)
	{ return i >= 0 && i < a->count ? &a->items[i] : NULL; }

void* heliArrayGetKey(HeliArray *a, int i) {
	HeliPair *item = heliArrayGet(a, i);
	return item ? item->key : NULL;
}

void* heliArrayGetValue(HeliArray *a, int i) {
	HeliPair *item = heliArrayGet(a, i);
	return item ? item->value : NULL;
}

HeliPair* heliArrayInsertPair(HeliArray *a, int i, void *k, void *v, HeliFreeCallback fk, HeliFreeCallback fv) {
	if (i < 0 || i > a->count)
		i = a->count;
	if (a->allocated < a->count + 1) {
		a->allocated += a->allocated/4 + 32;
		a->items = realloc(a->items, a->allocated*sizeof(a->items[0]));
		memset(&a->items[a->count], 0, (a->allocated - a->count)*sizeof(a->items[0]));
	}
	if (i < a->count) {
		memmove(&a->items[i+1], &a->items[i], (a->count-i)*sizeof(a->items[0]));
		memset(&a->items[i], 0, sizeof(a->items[0]));
	}
	++a->count;
	
	HeliPair *item = &a->items[i];
	item->key = k;
	item->value = v;
	item->freeKey = fk;
	item->freeValue = fv;
	return item;
}

HeliPair* heliArrayInsert(HeliArray *a, int i, void *v, HeliFreeCallback fv)
	{ return heliArrayInsertPair(a, i, NULL, NULL, v, fv); }

void heliArrayRemove(HeliArray *a, int i) {
	if (i < 0 || i >= a->count) return;
	heliPairDestroy(&a->items[i]);
	memmove(&a->items[i], &a->items[i+1], (a->count-i-1)*sizeof(a->items[0]));
	--a->count;
	memset(&a->items[a->count], 0, sizeof(a->items[0]));
}

void heliArrayClear(HeliArray *a) {
	while(a->count > 0)
		heliArrayRemove(a, a->count-1);
}

HeliPair* heliStringmapFind(HeliArray *a, const char *k, int *gtOrEqIndex) {
	int i0 = 0;
	int i1 = a->count - 1;
	int cmp = i0 < a->count ? strcmp((char*)a->items[i0].key, k) : -1;
	if (cmp >= 0) {
		if (gtOrEqIndex) *gtOrEqIndex = i0;
		return cmp ? NULL : &a->items[i0];
	}
	if (i1 > i0) cmp = strcmp((char*)a->items[i1].key, k);
	if (cmp <= 0) {
		if (gtOrEqIndex) *gtOrEqIndex = a->count;
		return cmp ? NULL : &a->items[i1];
	}
	
	while(i0 + 1 < i1) {
		int i = (i0 + i1)/2;
		cmp = strcmp((char*)a->items[i].key, k);
		if (cmp == 0) {
			if (gtOrEqIndex) *gtOrEqIndex = i;
			return &a->items[i];
		}
		if (cmp < 0) i0 = i; else i1 = i;
	}
	if (gtOrEqIndex) *gtOrEqIndex = i1;
	return NULL;
}

HeliPair* heliStringmapGet(HeliArray *a, const char *k)
	{ return heliStringmapFind(a, k, NULL); }

HeliPair* heliStringmapAdd(HeliArray *a, const char *k, void *v, HeliFreeCallback fv) {
	int i;
	HeliPair *item = heliStringmapFind(a, k, &i);
	if (item) {
		if (item->value && item->freeValue) item->freeValue(item->value);
		item->value = v;
		item->freeValue = fv;
	} else {
		item = heliArrayInsertPair(a, i, heliStringCopy(k), v, &free, fv);
	}
	return item;
}

int heliStringmapRemove(HeliArray *a, const char *k) {
	int i;
	if (heliStringmapFind(a, k, &i)) {
		heliArrayRemove(a, i);
		return TRUE;
	}
	return FALSE;
}