source: branches/blt4/src/objects/RpChain.c @ 2713

Last change on this file since 2713 was 1270, checked in by dkearney, 15 years ago

rappture object updates, stuff i'm playing around with. the code is not functional but it compiles, and i dont want to loose this state as i continue to play. the configure scripts and makefiles should still be working properly.

File size: 11.4 KB
Line 
1/*
2 * bltChain.c --
3 *
4 *  The module implements a generic linked list package.
5 *
6 * Copyright 1991-1998 Lucent Technologies, Inc.
7 *
8 * Permission to use, copy, modify, and distribute this software and
9 * its documentation for any purpose and without fee is hereby
10 * granted, provided that the above copyright notice appear in all
11 * copies and that both that the copyright notice and warranty
12 * disclaimer appear in supporting documentation, and that the names
13 * of Lucent Technologies any of their entities not be used in
14 * advertising or publicity pertaining to distribution of the software
15 * without specific, written prior permission.
16 *
17 * Lucent Technologies disclaims all warranties with regard to this
18 * software, including all implied warranties of merchantability and
19 * fitness.  In no event shall Lucent Technologies be liable for any
20 * special, indirect or consequential damages or any damages
21 * whatsoever resulting from loss of use, data or profits, whether in
22 * an action of contract, negligence or other tortuous action, arising
23 * out of or in connection with the use or performance of this
24 * software.
25 */
26
27#include "RpInt.h"
28#include "RpChain.h"
29
30#ifndef ALIGN
31#define ALIGN(a) \
32    (((size_t)a + (sizeof(double) - 1)) & (~(sizeof(double) - 1)))
33#endif /* ALIGN */
34
35/*
36 *----------------------------------------------------------------------
37 *
38 * Rp_ChainCreate --
39 *
40 *  Creates a new linked list (chain) structure and initializes
41 *  its pointers;
42 *
43 * Results:
44 *  Returns a pointer to the newly created chain structure.
45 *
46 *----------------------------------------------------------------------
47 */
48Rp_Chain *
49Rp_ChainCreate()
50{
51    Rp_Chain *chainPtr;
52
53    chainPtr = (Rp_Chain *) Rp_Malloc(sizeof(Rp_Chain));
54    if (chainPtr != NULL) {
55        Rp_ChainInit(chainPtr);
56    }
57    return chainPtr;
58}
59
60/*
61 *----------------------------------------------------------------------
62 *
63 * Rp_ChainAllocLink --
64 *
65 *  Creates a new chain link.  Unlink Rp_ChainNewLink, this
66 *  routine also allocates extra memory in the node for data.
67 *
68 * Results:
69 *  The return value is the pointer to the newly created entry.
70 *
71 *----------------------------------------------------------------------
72 */
73Rp_ChainLink *
74Rp_ChainAllocLink(extraSize)
75    unsigned int extraSize;
76{
77    Rp_ChainLink *linkPtr;
78    unsigned int linkSize;
79
80    linkSize = ALIGN(sizeof(Rp_ChainLink));
81    linkPtr = Rp_Calloc(1, linkSize + extraSize);
82    assert(linkPtr);
83    if (extraSize > 0) {
84        /* Point clientData at the memory beyond the normal structure. */
85        linkPtr->clientData = (ClientData)((char *)linkPtr + linkSize);
86    }
87    return linkPtr;
88}
89
90/*
91 *----------------------------------------------------------------------
92 *
93 * Rp_ChainNewLink --
94 *
95 *  Creates a new link.
96 *
97 * Results:
98 *  The return value is the pointer to the newly created link.
99 *
100 *----------------------------------------------------------------------
101 */
102Rp_ChainLink *
103Rp_ChainNewLink()
104{
105    Rp_ChainLink *linkPtr;
106
107    linkPtr = (Rp_ChainLink *) Rp_Malloc(sizeof(Rp_ChainLink));
108    assert(linkPtr);
109    linkPtr->clientData = NULL;
110    linkPtr->nextPtr = linkPtr->prevPtr = NULL;
111    return linkPtr;
112}
113
114/*
115 *----------------------------------------------------------------------
116 *
117 * Rp_ChainReset --
118 *
119 *  Removes all the links from the chain, freeing the memory for
120 *  each link.  Memory pointed to by the link (clientData) is not
121 *  freed.  It's the caller's responsibility to deallocate it.
122 *
123 * Results:
124 *  None.
125 *
126 *----------------------------------------------------------------------
127 */
128void
129Rp_ChainReset(chainPtr)
130    Rp_Chain *chainPtr; /* Chain to clear */
131{
132    if (chainPtr != NULL) {
133        Rp_ChainLink *oldPtr;
134        Rp_ChainLink *linkPtr = chainPtr->headPtr;
135
136        while (linkPtr != NULL) {
137            oldPtr = linkPtr;
138            linkPtr = linkPtr->nextPtr;
139            Rp_Free(oldPtr);
140        }
141        Rp_ChainInit(chainPtr);
142    }
143}
144
145/*
146 *----------------------------------------------------------------------
147 *
148 * Rp_ChainDestroy
149 *
150 *     Frees all the nodes from the chain and deallocates the memory
151 *     allocated for the chain structure itself.  It's assumed that
152 *     the chain was previous allocated by Rp_ChainCreate.
153 *
154 * Results:
155 *      None.
156 *
157 *----------------------------------------------------------------------
158 */
159void
160Rp_ChainDestroy(chainPtr)
161    Rp_Chain *chainPtr;
162{
163    if (chainPtr != NULL) {
164        Rp_ChainReset(chainPtr);
165        Rp_Free(chainPtr);
166    }
167}
168
169/*
170 *----------------------------------------------------------------------
171 *
172 * Rp_ChainInit --
173 *
174 *  Initializes a linked list.
175 *
176 * Results:
177 *  None.
178 *
179 *----------------------------------------------------------------------
180 */
181void
182Rp_ChainInit(chainPtr)
183    Rp_Chain *chainPtr;
184{
185    chainPtr->nLinks = 0;
186    chainPtr->headPtr = chainPtr->tailPtr = NULL;
187}
188
189/*
190 *----------------------------------------------------------------------
191 *
192 * Rp_ChainLinkAfter --
193 *
194 *  Inserts an entry following a given entry.
195 *
196 * Results:
197 *  None.
198 *
199 *----------------------------------------------------------------------
200 */
201void
202Rp_ChainLinkAfter(chainPtr, linkPtr, afterPtr)
203    Rp_Chain *chainPtr;
204    Rp_ChainLink *linkPtr, *afterPtr;
205{
206    if (chainPtr->headPtr == NULL) {
207        chainPtr->tailPtr = chainPtr->headPtr = linkPtr;
208    } else {
209        if (afterPtr == NULL) {
210            /* Prepend to the front of the chain */
211            linkPtr->nextPtr = chainPtr->headPtr;
212            linkPtr->prevPtr = NULL;
213            chainPtr->headPtr->prevPtr = linkPtr;
214            chainPtr->headPtr = linkPtr;
215        } else {
216            linkPtr->nextPtr = afterPtr->nextPtr;
217            linkPtr->prevPtr = afterPtr;
218            if (afterPtr == chainPtr->tailPtr) {
219                chainPtr->tailPtr = linkPtr;
220            } else {
221                afterPtr->nextPtr->prevPtr = linkPtr;
222            }
223            afterPtr->nextPtr = linkPtr;
224        }
225    }
226    chainPtr->nLinks++;
227}
228
229/*
230 *----------------------------------------------------------------------
231 *
232 * Rp_ChainLinkBefore --
233 *
234 *  Inserts a link preceding a given link.
235 *
236 * Results:
237 *  None.
238 *
239 *----------------------------------------------------------------------
240 */
241void
242Rp_ChainLinkBefore(chainPtr, linkPtr, beforePtr)
243    Rp_Chain *chainPtr;         /* Chain to contain new entry */
244    Rp_ChainLink *linkPtr;      /* New entry to be inserted */
245    Rp_ChainLink *beforePtr;    /* Entry to link before */
246{
247    if (chainPtr->headPtr == NULL) {
248        chainPtr->tailPtr = chainPtr->headPtr = linkPtr;
249    } else {
250        if (beforePtr == NULL) {
251            /* Append to the end of the chain. */
252            linkPtr->nextPtr = NULL;
253            linkPtr->prevPtr = chainPtr->tailPtr;
254            chainPtr->tailPtr->nextPtr = linkPtr;
255            chainPtr->tailPtr = linkPtr;
256        } else {
257            linkPtr->prevPtr = beforePtr->prevPtr;
258            linkPtr->nextPtr = beforePtr;
259            if (beforePtr == chainPtr->headPtr) {
260                chainPtr->headPtr = linkPtr;
261            } else {
262                beforePtr->prevPtr->nextPtr = linkPtr;
263            }
264            beforePtr->prevPtr = linkPtr;
265        }
266    }
267    chainPtr->nLinks++;
268}
269
270/*
271 *----------------------------------------------------------------------
272 *
273 * Rp_ChainUnlinkLink --
274 *
275 *      Unlinks a link from the chain. The link is not deallocated,
276 *      but only removed from the chain.
277 *
278 * Results:
279 *      None.
280 *
281 *----------------------------------------------------------------------
282 */
283void
284Rp_ChainUnlinkLink(chainPtr, linkPtr)
285    Rp_Chain *chainPtr;
286    Rp_ChainLink *linkPtr;
287{
288    int unlinked;       /* Indicates if the link is actually
289                         * removed from the chain. */
290
291    unlinked = FALSE;
292    if (chainPtr->headPtr == linkPtr) {
293        chainPtr->headPtr = linkPtr->nextPtr;
294        unlinked = TRUE;
295    }
296    if (chainPtr->tailPtr == linkPtr) {
297        chainPtr->tailPtr = linkPtr->prevPtr;
298        unlinked = TRUE;
299    }
300    if (linkPtr->nextPtr != NULL) {
301        linkPtr->nextPtr->prevPtr = linkPtr->prevPtr;
302        unlinked = TRUE;
303    }
304    if (linkPtr->prevPtr != NULL) {
305        linkPtr->prevPtr->nextPtr = linkPtr->nextPtr;
306        unlinked = TRUE;
307    }
308    if (unlinked) {
309        chainPtr->nLinks--;
310    }
311    linkPtr->prevPtr = linkPtr->nextPtr = NULL;
312}
313
314/*
315 *----------------------------------------------------------------------
316 *
317 * Rp_ChainDeleteLink --
318 *
319 *  Unlinks and also frees the given link.
320 *
321 * Results:
322 *  None.
323 *
324 *----------------------------------------------------------------------
325 */
326void
327Rp_ChainDeleteLink(chainPtr, linkPtr)
328    Rp_Chain *chainPtr;
329    Rp_ChainLink *linkPtr;
330{
331    Rp_ChainUnlinkLink(chainPtr, linkPtr);
332    Rp_Free(linkPtr);
333}
334
335Rp_ChainLink *
336Rp_ChainAppend(chainPtr, clientData)
337    Rp_Chain *chainPtr;
338    ClientData clientData;
339{
340    Rp_ChainLink *linkPtr;
341
342    linkPtr = Rp_ChainNewLink();
343    Rp_ChainLinkBefore(chainPtr, linkPtr, (Rp_ChainLink *)NULL);
344    Rp_ChainSetValue(linkPtr, clientData);
345    return linkPtr;
346}
347
348Rp_ChainLink *
349Rp_ChainPrepend(chainPtr, clientData)
350    Rp_Chain *chainPtr;
351    ClientData clientData;
352{
353    Rp_ChainLink *linkPtr;
354
355    linkPtr = Rp_ChainNewLink();
356    Rp_ChainLinkAfter(chainPtr, linkPtr, (Rp_ChainLink *)NULL);
357    Rp_ChainSetValue(linkPtr, clientData);
358    return linkPtr;
359}
360
361/*
362 *----------------------------------------------------------------------
363 *
364 * Rp_ChainGetNthLink --
365 *
366 *  Find the link at the given position in the chain.
367 *
368 * Results:
369 *  Returns the pointer to the link, if that numbered link
370 *  exists. Otherwise NULL.
371 *
372 *----------------------------------------------------------------------
373 */
374Rp_ChainLink *
375Rp_ChainGetNthLink(chainPtr, position)
376    Rp_Chain *chainPtr; /* Chain to traverse */
377    int position;       /* Index of link to select from front
378                         * or back of the chain. */
379{
380    Rp_ChainLink *linkPtr;
381
382    if (chainPtr != NULL) {
383        for (linkPtr = chainPtr->headPtr; linkPtr != NULL;
384            linkPtr = linkPtr->nextPtr) {
385            if (position == 0) {
386                return linkPtr;
387            }
388            position--;
389        }
390    }
391    return NULL;
392}
393
394/*
395 *----------------------------------------------------------------------
396 *
397 * Rp_ChainSort --
398 *
399 *  Sorts the chain according to the given comparison routine.
400 *
401 * Results:
402 *  None.
403 *
404 * Side Effects:
405 *  The chain is reordered.
406 *
407 *----------------------------------------------------------------------
408 */
409void
410Rp_ChainSort(chainPtr, proc)
411    Rp_Chain *chainPtr; /* Chain to traverse */
412    Rp_ChainCompareProc *proc;
413{
414    Rp_ChainLink **linkArr;
415    register Rp_ChainLink *linkPtr;
416    register int i;
417
418    if (chainPtr->nLinks < 2) {
419        return;
420    }
421    linkArr = (Rp_ChainLink **) Rp_Malloc(sizeof(Rp_ChainLink *) * (chainPtr->nLinks + 1));
422    if (linkArr == NULL) {
423        return;         /* Out of memory. */
424    }
425    i = 0;
426    for (linkPtr = chainPtr->headPtr; linkPtr != NULL;
427         linkPtr = linkPtr->nextPtr) {
428        linkArr[i++] = linkPtr;
429    }
430    qsort((char *)linkArr, chainPtr->nLinks, sizeof(Rp_ChainLink *),
431        (QSortCompareProc *)proc);
432
433    /* Rethread the chain. */
434    linkPtr = linkArr[0];
435    chainPtr->headPtr = linkPtr;
436    linkPtr->prevPtr = NULL;
437    for (i = 1; i < chainPtr->nLinks; i++) {
438        linkPtr->nextPtr = linkArr[i];
439        linkPtr->nextPtr->prevPtr = linkPtr;
440        linkPtr = linkPtr->nextPtr;
441    }
442    chainPtr->tailPtr = linkPtr;
443    linkPtr->nextPtr = NULL;
444    Rp_Free(linkArr);
445}
Note: See TracBrowser for help on using the repository browser.