108 lines
2.6 KiB
C
108 lines
2.6 KiB
C
|
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
|
||
|
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
/* get length of a singly linked list */
|
||
|
size_t SLlength(void *head, size_t offset)
|
||
|
{
|
||
|
size_t nelem = 0;
|
||
|
|
||
|
while (head) {
|
||
|
/*LINTED*/
|
||
|
head = *(void **)((char *)head + offset);
|
||
|
nelem++;
|
||
|
}
|
||
|
return nelem;
|
||
|
}
|
||
|
|
||
|
/* search for an element in a singly linked list */
|
||
|
int SLcontains(void *head, size_t offset, void *elem)
|
||
|
{
|
||
|
while (head) {
|
||
|
if (head == elem)
|
||
|
return 1;
|
||
|
/*LINTED pointer cast may result in improper alignment*/
|
||
|
head = *(void **)((char *)head + offset);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* copy elements of a singly linked list into an array */
|
||
|
void SLtoA(void *head, size_t offset, size_t elemsize, void **base, size_t *nelem)
|
||
|
{
|
||
|
void *p;
|
||
|
|
||
|
*nelem = SLlength(head, offset);
|
||
|
if (!*nelem) {
|
||
|
*base = NULL;
|
||
|
return;
|
||
|
}
|
||
|
p = *base = malloc(*nelem * elemsize);
|
||
|
/*LINTED*/
|
||
|
for (; head; head = *(void **)((char *)head + offset)) {
|
||
|
memcpy(p, head, elemsize);
|
||
|
p = (void *)((char *)p + elemsize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* copy pointers to elements of a singly linked list into an array */
|
||
|
void SLtoAP(void *head, size_t offset, void ***base, size_t *nelem)
|
||
|
{
|
||
|
void **p;
|
||
|
|
||
|
*nelem = SLlength(head, offset);
|
||
|
if (!*nelem) {
|
||
|
*base = NULL;
|
||
|
return;
|
||
|
}
|
||
|
p = *base = (void **)malloc(*nelem * sizeof(void *));
|
||
|
/*LINTED*/
|
||
|
for (; head; head = *(void **)((char *)head + offset)) {
|
||
|
*p++ = head;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* copy elements of an array into a singly linked list */
|
||
|
void AtoSL(void *base, size_t offset, size_t nelem, size_t elemsize, void **head)
|
||
|
{
|
||
|
while (nelem--) {
|
||
|
*head = malloc(elemsize);
|
||
|
memcpy(*head, base, elemsize);
|
||
|
base = (void *)((char *)base + elemsize);
|
||
|
/*LINTED*/
|
||
|
head = (void **)((char *)*head + offset);
|
||
|
}
|
||
|
*head = NULL;
|
||
|
}
|
||
|
|
||
|
/* user defined compare function of qsortSL */
|
||
|
static int (*qsortSL_CmpFnCb)(const void *, const void *, void *);
|
||
|
static void *qsortSL_Context;
|
||
|
|
||
|
/* compare function of qsortSL */
|
||
|
static int __cdecl qsortSL_CmpFn(const void *p1, const void *p2)
|
||
|
{
|
||
|
return qsortSL_CmpFnCb(*(void **)p1, *(void **)p2, qsortSL_Context);
|
||
|
}
|
||
|
|
||
|
/* sort a singly linked list */
|
||
|
void qsortSL(void **head, size_t offset, int (*cmpfn)(const void *, const void *, void *), void *context)
|
||
|
{
|
||
|
void **base, **p;
|
||
|
size_t nelem;
|
||
|
|
||
|
SLtoAP(*head, offset, &base, &nelem);
|
||
|
qsortSL_CmpFnCb = cmpfn;
|
||
|
qsortSL_Context = context;
|
||
|
qsort(base, nelem, sizeof(void *), qsortSL_CmpFn);
|
||
|
p = base;
|
||
|
while (nelem--) {
|
||
|
*head = *p++;
|
||
|
/*LINTED*/
|
||
|
head = (void **)((char *)*head + offset);
|
||
|
}
|
||
|
*head = NULL;
|
||
|
free(base);
|
||
|
}
|