1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 /*[]---------------------------------------------------[]*/
30 /*| list.c - bidirectional list class |*/
33 /*| Author: Alexander Gelfenbain |*/
34 /*[]---------------------------------------------------[]*/
38 #if OSL_DEBUG_LEVEL == 0
48 #include </usr/local/include/malloc.h>
53 /*- private data types */
54 typedef struct _lnode
{
63 lnode
*head
, *tail
, *cptr
;
65 list_destructor eDtor
;
68 /*- private methods */
70 static lnode
*newNode(void *el
)
72 lnode
*ptr
= malloc(sizeof(lnode
));
80 static lnode
*appendPrim(list
this, void *el
)
82 lnode
*ptr
= newNode(el
);
83 lnode
**flink
, *blink
;
85 if (this->tail
!= 0) {
86 flink
= &(this->tail
->next
);
91 this->cptr
= ptr
; /*- list was empty - set current to this element */
104 static lnode
*prependPrim(list
this, void *el
)
106 lnode
*ptr
= newNode(el
);
107 lnode
*flink
, **blink
;
109 if (this->head
!= 0) {
110 blink
= &(this->head
->prev
);
115 this->cptr
= ptr
; /*- list was empty - set current to this element */
129 /*- public methods */
130 list
listNewEmpty(void) /*- default ctor */
132 list
this = malloc(sizeof(struct _list
));
137 this->head
= this->tail
= this->cptr
= 0;
143 list
listNewCopy(list l
) /*- copy ctor */
149 this = malloc(sizeof(struct _list
));
156 this->head
= this->tail
= this->cptr
= 0;
159 c
= appendPrim(this, ptr
->value
);
160 if (ptr
== l
->cptr
) this->cptr
= c
;
168 void listDispose(list
this) /*- dtor */
175 void listSetElementDtor(list
this, list_destructor f
)
181 /* calling this function on an empty list is a run-time error */
182 void *listCurrent(list
this)
185 assert(this->cptr
!= 0);
186 return this->cptr
->value
;
189 int listCount(list
this)
195 int listIsEmpty(list
this)
198 return this->aCount
== 0;
203 int listAtFirst(list
this)
206 return this->cptr
== this->head
;
209 int listAtLast(list
this)
212 return this->cptr
== this->tail
;
215 int listPosition(list
this)
223 while (ptr
!= this->cptr
) {
231 int listFind(list
this, void *el
)
239 if (ptr
->value
== el
) {
249 int listNext(list
this)
251 return listSkipForward(this, 1);
254 int listSkipForward(list
this, int n
)
259 if (this->cptr
== 0) return 0;
262 if (this->cptr
->next
== 0) break;
263 this->cptr
= this->cptr
->next
;
270 int listToFirst(list
this)
274 if (this->cptr
!= this->head
) {
275 this->cptr
= this->head
;
281 int listToLast(list
this)
285 if (this->cptr
!= this->tail
) {
286 this->cptr
= this->tail
;
292 int listPositionAt(list
this, int n
) /*- returns the actual position number */
297 this->cptr
= this->head
;
299 if (this->cptr
->next
== 0) break;
300 this->cptr
= this->cptr
->next
;
307 list
listAppend(list
this, void *el
)
311 appendPrim(this, el
);
315 list
listPrepend(list
this, void *el
)
319 prependPrim(this, el
);
323 list
listInsertAfter(list
this, void *el
)
328 if (this->cptr
== 0) return listAppend(this, el
);
332 ptr
->prev
= this->cptr
;
333 ptr
->next
= this->cptr
->next
;
334 this->cptr
->next
= ptr
;
336 if (ptr
->next
!= 0) {
337 ptr
->next
->prev
= ptr
;
345 list
listInsertBefore(list
this, void *el
)
350 if (this->cptr
== 0) return listAppend(this, el
);
354 ptr
->prev
= this->cptr
->prev
;
355 ptr
->next
= this->cptr
;
356 this->cptr
->prev
= ptr
;
358 if (ptr
->prev
!= 0) {
359 ptr
->prev
->next
= ptr
;
367 list
listRemove(list
this)
370 if (this->cptr
== 0) return this;
372 if (this->cptr
->next
!= 0) {
373 ptr
= this->cptr
->next
;
374 this->cptr
->next
->prev
= this->cptr
->prev
;
376 this->tail
= this->cptr
->prev
;
379 if (this->cptr
->prev
!= 0) {
380 if (ptr
== 0) ptr
= this->cptr
->prev
;
381 this->cptr
->prev
->next
= this->cptr
->next
;
383 this->head
= this->cptr
->next
;
386 if (this->eDtor
) this->eDtor(this->cptr
->value
); /* call the dtor callback */
394 list
listClear(list
this)
396 lnode
*node
= this->head
, *ptr
;
400 if (this->eDtor
) this->eDtor(node
->value
); /* call the dtor callback */
406 this->head
= this->tail
= this->cptr
= 0;
407 assert(this->aCount
== 0);
413 void listForAll(list
this, void (*f
)(void *))
415 lnode
*ptr
= this->head
;
425 void printlist(list l
)
429 saved
= listPosition(l
);
433 if (!listIsEmpty(l
)) {
436 printf("%d ", (int) listCurrent(l
));
437 } while (listNext(l
));
442 listPositionAt(l
, saved
);
445 void printstringlist(list l
)
449 saved
= listPosition(l
);
453 if (!listIsEmpty(l
)) {
456 printf("'%s' ", (char *) listCurrent(l
));
457 } while (listNext(l
));
462 listPositionAt(l
, saved
);
465 void printstat(list l
)
467 printf("count: %d, position: %d, isEmpty: %d, atFirst: %d, atLast: %d.\n",
468 listCount(l
), listPosition(l
), listIsEmpty(l
), listAtFirst(l
), listAtLast(l
));
471 void allfunc(void *e
)
476 void edtor(void *ptr
)
478 printf("element dtor: 0x%08x\n", ptr
);
508 listInsertBefore(l1
, -5);
511 l2
= listNewCopy(l1
);
514 listForAll(l2
, allfunc
);
518 listSetElementDtor(l1
, edtor
);
520 for(i
=0; i
<10; i
++) {
522 snprintf(ptr
, 20, "element # %d", i
);
533 mal_dumpleaktrace(stdout
);