forked from github/server
152 lines
3.1 KiB
C
152 lines
3.1 KiB
C
/* vi: set ts=2:
|
|
*
|
|
* $Id: cvector.c,v 1.2 2001/01/26 16:19:41 enno Exp $
|
|
* Eressea PB(E)M host Copyright (C) 1998-2000
|
|
* Christian Schlittchen (corwin@amber.kn-bremen.de)
|
|
* Katja Zedel (katze@felidae.kn-bremen.de)
|
|
* Henning Peters (faroul@beyond.kn-bremen.de)
|
|
* Enno Rehling (enno@eressea-pbem.de)
|
|
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
*
|
|
* based on:
|
|
*
|
|
* Atlantis v1.0 13 September 1993 Copyright 1993 by Russell Wallace
|
|
* Atlantis v1.7 Copyright 1996 by Alex Schröder
|
|
*
|
|
* This program may not be used, modified or distributed without
|
|
* prior permission by the authors of Eressea.
|
|
* This program may not be sold or used commercially without prior written
|
|
* permission from the authors.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <limits.h>
|
|
#include <config.h>
|
|
#include "cvector.h"
|
|
#include "memory.h"
|
|
|
|
void
|
|
cv_init(cvector * cv)
|
|
{
|
|
cv->begin = 0;
|
|
cv->end = 0;
|
|
cv->space = 0;
|
|
}
|
|
|
|
cvector *
|
|
cv_kill(cvector * cv)
|
|
{
|
|
if (cv->begin) free(cv->begin);
|
|
cv_init(cv);
|
|
return cv;
|
|
}
|
|
|
|
size_t
|
|
cv_size(cvector * cv)
|
|
{
|
|
return cv->end - cv->begin;
|
|
}
|
|
|
|
void
|
|
cv_reserve(cvector * cv, size_t size)
|
|
{
|
|
size_t count = cv->end - cv->begin;
|
|
cv->begin = realloc(cv->begin, size * sizeof(void *));
|
|
|
|
cv->space = size;
|
|
cv->end = cv->begin + count;
|
|
}
|
|
|
|
void
|
|
cv_pushback(cvector * cv, void *u)
|
|
{
|
|
if (cv->space == cv_size(cv))
|
|
cv_reserve(cv, cv->space ? cv->space * 2 : 2);
|
|
*(cv->end++) = u;
|
|
}
|
|
|
|
void
|
|
v_sort(void **begin, void **end, int (__cdecl * compare) (const void *, const void *))
|
|
{
|
|
qsort(begin, end - begin, sizeof(void *), compare);
|
|
}
|
|
|
|
void **
|
|
v_find(void **begin, void **end, void *item)
|
|
{
|
|
void **it;
|
|
|
|
for (it = begin; it != end; ++it)
|
|
if (*it == item)
|
|
return it;
|
|
return it;
|
|
}
|
|
|
|
void **
|
|
v_findx(void **begin, void **end, void *item, int (__cdecl * cmp) (void *, void *))
|
|
{
|
|
void **it;
|
|
|
|
for (it = begin; it != end; ++it)
|
|
if (cmp(*it, item))
|
|
return it;
|
|
return it;
|
|
}
|
|
|
|
int
|
|
__cv_scramblecmp(const void *p1, const void *p2)
|
|
{
|
|
return *((long *) p1) - *((long *) p2);
|
|
}
|
|
|
|
#define addptr(p,i) ((void *)(((char *)p) + i))
|
|
|
|
void
|
|
__cv_scramble(void *v1, int n, size_t width)
|
|
{
|
|
int i;
|
|
static size_t s = 0;
|
|
static void *v = 0;
|
|
|
|
if (n * (width + 4) > s) {
|
|
s = n * (width + 4);
|
|
v = (void *) realloc(v, s);
|
|
}
|
|
for (i = 0; i != n; i++) {
|
|
*(long *) addptr(v, i * (width + 4)) = rand();
|
|
memcpy(addptr(v, i * (width + 4) + 4), addptr(v1, i * width), width);
|
|
}
|
|
|
|
qsort(v, n, width + 4, __cv_scramblecmp);
|
|
|
|
for (i = 0; i != n; i++)
|
|
memcpy(addptr(v1, i * width), addptr(v, i * (width + 4) + 4), width);
|
|
|
|
}
|
|
|
|
void
|
|
v_scramble(void **begin, void **end)
|
|
{
|
|
__cv_scramble(begin, end - begin, sizeof(void *));
|
|
}
|
|
|
|
void
|
|
cv_mergeunique(cvector * c, const cvector * a, const cvector * b, int (__cdecl * keyfun) (const void *))
|
|
{
|
|
void **ai, **bi;
|
|
|
|
assert(cv_size(c) == 0);
|
|
|
|
for (ai = a->begin, bi = b->begin; ai != a->end || bi != b->end;) {
|
|
int ak = (ai == a->end) ? INT_MAX : keyfun(*ai);
|
|
int bk = (bi == b->end) ? INT_MAX : keyfun(*bi);
|
|
int nk = (ak < bk) ? ak : bk;
|
|
|
|
cv_pushback(c, (ak == nk) ? (*ai) : (*bi));
|
|
while (ai != a->end && keyfun(*ai) == nk)
|
|
++ai;
|
|
while (bi != b->end && keyfun(*bi) == nk)
|
|
++bi;
|
|
}
|
|
}
|