source: trunk/kitgen/8.x/blt/generic/bltList.c@ 199

Last change on this file since 199 was 175, checked in by demin, 12 years ago

initial commit

File size: 14.2 KB
Line 
1/*
2 * bltList.c --
3 *
4 * The module implements generic linked lists.
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 "bltInt.h"
28#include "bltList.h"
29
30static struct Blt_ListNodeStruct *
31FindString(listPtr, key)
32 struct Blt_ListStruct *listPtr; /* List to search */
33 CONST char *key; /* Key to match */
34{
35 register struct Blt_ListNodeStruct *nodePtr;
36 char c;
37
38 c = key[0];
39 for (nodePtr = listPtr->headPtr; nodePtr != NULL;
40 nodePtr = nodePtr->nextPtr) {
41 if ((c == nodePtr->key.string[0]) &&
42 (strcmp(key, nodePtr->key.string) == 0)) {
43 return nodePtr;
44 }
45 }
46 return NULL;
47}
48
49static Blt_ListNode
50FindOneWord(listPtr, key)
51 struct Blt_ListStruct *listPtr; /* List to search */
52 CONST char *key; /* Key to match */
53{
54 register struct Blt_ListNodeStruct *nodePtr;
55
56 for (nodePtr = listPtr->headPtr; nodePtr != NULL;
57 nodePtr = nodePtr->nextPtr) {
58 if (key == nodePtr->key.oneWordValue) {
59 return nodePtr;
60 }
61 }
62 return NULL;
63}
64
65static Blt_ListNode
66FindArray(listPtr, key)
67 struct Blt_ListStruct *listPtr; /* List to search */
68 CONST char *key; /* Key to match */
69{
70 register struct Blt_ListNodeStruct *nodePtr;
71 int nBytes;
72
73 nBytes = sizeof(int) * listPtr->type;
74 for (nodePtr = listPtr->headPtr; nodePtr != NULL;
75 nodePtr = nodePtr->nextPtr) {
76 if (memcmp(key, nodePtr->key.words, nBytes) == 0) {
77 return nodePtr;
78 }
79 }
80 return NULL;
81}
82
83/*
84 *----------------------------------------------------------------------
85 *
86 * FreeNode --
87 *
88 * Free the memory allocated for the node.
89 *
90 * Results:
91 * None.
92 *
93 *----------------------------------------------------------------------
94 */
95static void
96FreeNode(nodePtr)
97 struct Blt_ListNodeStruct *nodePtr;
98{
99 Blt_Free(nodePtr);
100}
101
102/*
103 *----------------------------------------------------------------------
104 *
105 * Blt_ListCreate --
106 *
107 * Creates a new linked list structure and initializes its pointers
108 *
109 * Results:
110 * Returns a pointer to the newly created list structure.
111 *
112 *----------------------------------------------------------------------
113 */
114/*LINTLIBRARY*/
115Blt_List
116Blt_ListCreate(type)
117 int type;
118{
119 struct Blt_ListStruct *listPtr;
120
121 listPtr = Blt_Malloc(sizeof(struct Blt_ListStruct));
122 if (listPtr != NULL) {
123 Blt_ListInit(listPtr, type);
124 }
125 return listPtr;
126}
127
128/*
129 *----------------------------------------------------------------------
130 *
131 * Blt_ListCreateNode --
132 *
133 * Creates a list node holder. This routine does not insert
134 * the node into the list, nor does it no attempt to maintain
135 * consistency of the keys. For example, more than one node
136 * may use the same key.
137 *
138 * Results:
139 * The return value is the pointer to the newly created node.
140 *
141 * Side Effects:
142 * The key is not copied, only the Uid is kept. It is assumed
143 * this key will not change in the life of the node.
144 *
145 *----------------------------------------------------------------------
146 */
147/*LINTLIBRARY*/
148Blt_ListNode
149Blt_ListCreateNode(listPtr, key)
150 struct Blt_ListStruct *listPtr;
151 CONST char *key; /* Unique key to reference object */
152{
153 register struct Blt_ListNodeStruct *nodePtr;
154 int keySize;
155
156 if (listPtr->type == BLT_STRING_KEYS) {
157 keySize = strlen(key) + 1;
158 } else if (listPtr->type == BLT_ONE_WORD_KEYS) {
159 keySize = sizeof(int);
160 } else {
161 keySize = sizeof(int) * listPtr->type;
162 }
163 nodePtr = Blt_Calloc(1, sizeof(struct Blt_ListNodeStruct) + keySize - 4);
164 assert(nodePtr);
165 nodePtr->clientData = NULL;
166 nodePtr->nextPtr = nodePtr->prevPtr = NULL;
167 nodePtr->listPtr = listPtr;
168 switch (listPtr->type) {
169 case BLT_STRING_KEYS:
170 strcpy(nodePtr->key.string, key);
171 break;
172 case BLT_ONE_WORD_KEYS:
173 nodePtr->key.oneWordValue = key;
174 break;
175 default:
176 memcpy(nodePtr->key.words, key, keySize);
177 break;
178 }
179 return nodePtr;
180}
181
182/*
183 *----------------------------------------------------------------------
184 *
185 * Blt_ListReset --
186 *
187 * Removes all the entries from a list, removing pointers to the
188 * objects and keys (not the objects or keys themselves). The
189 * node counter is reset to zero.
190 *
191 * Results:
192 * None.
193 *
194 *----------------------------------------------------------------------
195 */
196/*LINTLIBRARY*/
197void
198Blt_ListReset(listPtr)
199 struct Blt_ListStruct *listPtr; /* List to clear */
200{
201 if (listPtr != NULL) {
202 register struct Blt_ListNodeStruct *oldPtr;
203 register struct Blt_ListNodeStruct *nodePtr = listPtr->headPtr;
204
205 while (nodePtr != NULL) {
206 oldPtr = nodePtr;
207 nodePtr = nodePtr->nextPtr;
208 FreeNode(oldPtr);
209 }
210 Blt_ListInit(listPtr, listPtr->type);
211 }
212}
213
214/*
215 *----------------------------------------------------------------------
216 *
217 * Blt_ListDestroy
218 *
219 * Frees all list structures
220 *
221 * Results:
222 * Returns a pointer to the newly created list structure.
223 *
224 *----------------------------------------------------------------------
225 */
226/*LINTLIBRARY*/
227void
228Blt_ListDestroy(listPtr)
229 struct Blt_ListStruct *listPtr;
230{
231 if (listPtr != NULL) {
232 Blt_ListReset(listPtr);
233 Blt_Free(listPtr);
234 }
235}
236
237/*
238 *----------------------------------------------------------------------
239 *
240 * Blt_ListInit --
241 *
242 * Initializes a linked list.
243 *
244 * Results:
245 * None.
246 *
247 *----------------------------------------------------------------------
248 */
249/*LINTLIBRARY*/
250void
251Blt_ListInit(listPtr, type)
252 struct Blt_ListStruct *listPtr;
253 int type;
254{
255 listPtr->nNodes = 0;
256 listPtr->headPtr = listPtr->tailPtr = NULL;
257 listPtr->type = type;
258}
259
260/*
261 *----------------------------------------------------------------------
262 *
263 * Blt_ListLinkAfter --
264 *
265 * Inserts an node following a given node.
266 *
267 * Results:
268 * None.
269 *
270 *----------------------------------------------------------------------
271 */
272/*LINTLIBRARY*/
273void
274Blt_ListLinkAfter(listPtr, nodePtr, afterPtr)
275 struct Blt_ListStruct *listPtr;
276 struct Blt_ListNodeStruct *nodePtr;
277 struct Blt_ListNodeStruct *afterPtr;
278{
279 if (listPtr->headPtr == NULL) {
280 listPtr->tailPtr = listPtr->headPtr = nodePtr;
281 } else {
282 if (afterPtr == NULL) {
283 /* Prepend to the front of the list */
284 nodePtr->nextPtr = listPtr->headPtr;
285 nodePtr->prevPtr = NULL;
286 listPtr->headPtr->prevPtr = nodePtr;
287 listPtr->headPtr = nodePtr;
288 } else {
289 nodePtr->nextPtr = afterPtr->nextPtr;
290 nodePtr->prevPtr = afterPtr;
291 if (afterPtr == listPtr->tailPtr) {
292 listPtr->tailPtr = nodePtr;
293 } else {
294 afterPtr->nextPtr->prevPtr = nodePtr;
295 }
296 afterPtr->nextPtr = nodePtr;
297 }
298 }
299 nodePtr->listPtr = listPtr;
300 listPtr->nNodes++;
301}
302
303/*
304 *----------------------------------------------------------------------
305 *
306 * Blt_ListLinkBefore --
307 *
308 * Inserts an node preceding a given node.
309 *
310 * Results:
311 * None.
312 *
313 *----------------------------------------------------------------------
314 */
315/*LINTLIBRARY*/
316void
317Blt_ListLinkBefore(listPtr, nodePtr, beforePtr)
318 struct Blt_ListStruct *listPtr; /* List to contain new node */
319 struct Blt_ListNodeStruct *nodePtr; /* New node to be inserted */
320 struct Blt_ListNodeStruct *beforePtr; /* Node to link before */
321{
322 if (listPtr->headPtr == NULL) {
323 listPtr->tailPtr = listPtr->headPtr = nodePtr;
324 } else {
325 if (beforePtr == NULL) {
326 /* Append onto the end of the list */
327 nodePtr->nextPtr = NULL;
328 nodePtr->prevPtr = listPtr->tailPtr;
329 listPtr->tailPtr->nextPtr = nodePtr;
330 listPtr->tailPtr = nodePtr;
331 } else {
332 nodePtr->prevPtr = beforePtr->prevPtr;
333 nodePtr->nextPtr = beforePtr;
334 if (beforePtr == listPtr->headPtr) {
335 listPtr->headPtr = nodePtr;
336 } else {
337 beforePtr->prevPtr->nextPtr = nodePtr;
338 }
339 beforePtr->prevPtr = nodePtr;
340 }
341 }
342 nodePtr->listPtr = listPtr;
343 listPtr->nNodes++;
344}
345
346/*
347 *----------------------------------------------------------------------
348 *
349 * Blt_ListUnlinkNode --
350 *
351 * Unlinks an node from the given list. The node itself is
352 * not deallocated, but only removed from the list.
353 *
354 * Results:
355 * None.
356 *
357 *----------------------------------------------------------------------
358 */
359/*LINTLIBRARY*/
360void
361Blt_ListUnlinkNode(nodePtr)
362 struct Blt_ListNodeStruct *nodePtr;
363{
364 struct Blt_ListStruct *listPtr;
365
366 listPtr = nodePtr->listPtr;
367 if (listPtr != NULL) {
368 if (listPtr->headPtr == nodePtr) {
369 listPtr->headPtr = nodePtr->nextPtr;
370 }
371 if (listPtr->tailPtr == nodePtr) {
372 listPtr->tailPtr = nodePtr->prevPtr;
373 }
374 if (nodePtr->nextPtr != NULL) {
375 nodePtr->nextPtr->prevPtr = nodePtr->prevPtr;
376 }
377 if (nodePtr->prevPtr != NULL) {
378 nodePtr->prevPtr->nextPtr = nodePtr->nextPtr;
379 }
380 nodePtr->listPtr = NULL;
381 listPtr->nNodes--;
382 }
383}
384
385/*
386 *----------------------------------------------------------------------
387 *
388 * Blt_ListGetNode --
389 *
390 * Find the first node matching the key given.
391 *
392 * Results:
393 * Returns the pointer to the node. If no node matching
394 * the key given is found, then NULL is returned.
395 *
396 *----------------------------------------------------------------------
397 */
398
399/*LINTLIBRARY*/
400Blt_ListNode
401Blt_ListGetNode(listPtr, key)
402 struct Blt_ListStruct *listPtr; /* List to search */
403 CONST char *key; /* Key to match */
404{
405 if (listPtr != NULL) {
406 switch (listPtr->type) {
407 case BLT_STRING_KEYS:
408 return FindString(listPtr, key);
409 case BLT_ONE_WORD_KEYS:
410 return FindOneWord(listPtr, key);
411 default:
412 return FindArray(listPtr, key);
413 }
414 }
415 return NULL;
416}
417
418/*
419 *----------------------------------------------------------------------
420 *
421 * Blt_ListDeleteNode --
422 *
423 * Unlinks and deletes the given node.
424 *
425 * Results:
426 * None.
427 *
428 *----------------------------------------------------------------------
429 */
430/*LINTLIBRARY*/
431void
432Blt_ListDeleteNode(nodePtr)
433 struct Blt_ListNodeStruct *nodePtr;
434{
435 Blt_ListUnlinkNode(nodePtr);
436 FreeNode(nodePtr);
437}
438
439/*
440 *----------------------------------------------------------------------
441 *
442 * Blt_ListDeleteNodeByKey --
443 *
444 * Find the node and free the memory allocated for the node.
445 *
446 * Results:
447 * None.
448 *
449 *----------------------------------------------------------------------
450 */
451/*LINTLIBRARY*/
452void
453Blt_ListDeleteNodeByKey(listPtr, key)
454 struct Blt_ListStruct *listPtr;
455 CONST char *key;
456{
457 struct Blt_ListNodeStruct *nodePtr;
458
459 nodePtr = Blt_ListGetNode(listPtr, key);
460 if (nodePtr != NULL) {
461 Blt_ListDeleteNode(nodePtr);
462 }
463}
464
465/*LINTLIBRARY*/
466Blt_ListNode
467Blt_ListAppend(listPtr, key, clientData)
468 struct Blt_ListStruct *listPtr;
469 CONST char *key;
470 ClientData clientData;
471{
472 struct Blt_ListNodeStruct *nodePtr;
473
474 nodePtr = Blt_ListCreateNode(listPtr, key);
475 Blt_ListSetValue(nodePtr, clientData);
476 Blt_ListAppendNode(listPtr, nodePtr);
477 return nodePtr;
478}
479
480/*LINTLIBRARY*/
481Blt_ListNode
482Blt_ListPrepend(listPtr, key, clientData)
483 struct Blt_ListStruct *listPtr;
484 CONST char *key;
485 ClientData clientData;
486{
487 struct Blt_ListNodeStruct *nodePtr;
488
489 nodePtr = Blt_ListCreateNode(listPtr, key);
490 Blt_ListSetValue(nodePtr, clientData);
491 Blt_ListPrependNode(listPtr, nodePtr);
492 return nodePtr;
493}
494
495/*
496 *----------------------------------------------------------------------
497 *
498 * Blt_ListGetNthNode --
499 *
500 * Find the node based upon a given position in list.
501 *
502 * Results:
503 * Returns the pointer to the node, if that numbered element
504 * exists. Otherwise NULL.
505 *
506 *----------------------------------------------------------------------
507 */
508/*LINTLIBRARY*/
509Blt_ListNode
510Blt_ListGetNthNode(listPtr, position, direction)
511 struct Blt_ListStruct *listPtr; /* List to traverse */
512 int position; /* Index of node to select from front
513 * or back of the list. */
514 int direction;
515{
516 register struct Blt_ListNodeStruct *nodePtr;
517
518 if (listPtr != NULL) {
519 if (direction > 0) {
520 for (nodePtr = listPtr->headPtr; nodePtr != NULL;
521 nodePtr = nodePtr->nextPtr) {
522 if (position == 0) {
523 return nodePtr;
524 }
525 position--;
526 }
527 } else {
528 for (nodePtr = listPtr->tailPtr; nodePtr != NULL;
529 nodePtr = nodePtr->prevPtr) {
530 if (position == 0) {
531 return nodePtr;
532 }
533 position--;
534 }
535 }
536 }
537 return NULL;
538}
539
540/*
541 *----------------------------------------------------------------------
542 *
543 * Blt_ListSort --
544 *
545 * Find the node based upon a given position in list.
546 *
547 * Results:
548 * Returns the pointer to the node, if that numbered element
549 * exists. Otherwise NULL.
550 *
551 *----------------------------------------------------------------------
552 */
553/*LINTLIBRARY*/
554void
555Blt_ListSort(listPtr, proc)
556 struct Blt_ListStruct *listPtr; /* List to traverse */
557 Blt_ListCompareProc *proc;
558{
559 struct Blt_ListNodeStruct **nodeArr;
560 register struct Blt_ListNodeStruct *nodePtr;
561 register int i;
562
563 if (listPtr->nNodes < 2) {
564 return;
565 }
566 nodeArr = Blt_Malloc(sizeof(Blt_List) * (listPtr->nNodes + 1));
567 if (nodeArr == NULL) {
568 return; /* Out of memory. */
569 }
570 i = 0;
571 for (nodePtr = listPtr->headPtr; nodePtr != NULL;
572 nodePtr = nodePtr->nextPtr) {
573 nodeArr[i++] = nodePtr;
574 }
575 qsort((char *)nodeArr, listPtr->nNodes,
576 sizeof(struct Blt_ListNodeStruct *), (QSortCompareProc *)proc);
577
578 /* Rethread the list. */
579 nodePtr = nodeArr[0];
580 listPtr->headPtr = nodePtr;
581 nodePtr->prevPtr = NULL;
582 for (i = 1; i < listPtr->nNodes; i++) {
583 nodePtr->nextPtr = nodeArr[i];
584 nodePtr->nextPtr->prevPtr = nodePtr;
585 nodePtr = nodePtr->nextPtr;
586 }
587 listPtr->tailPtr = nodePtr;
588 nodePtr->nextPtr = NULL;
589 Blt_Free(nodeArr);
590}
Note: See TracBrowser for help on using the repository browser.