xref: /aoo42x/main/vcl/source/fontsubset/list.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 /*[]---------------------------------------------------[]*/
29 /*|                                                     |*/
30 /*|     list.c - bidirectional list class               |*/
31 /*|                                                     |*/
32 /*|                                                     |*/
33 /*|  Author: Alexander Gelfenbain                       |*/
34 /*[]---------------------------------------------------[]*/
35 
36 #include <stdlib.h>
37 
38 #if OSL_DEBUG_LEVEL == 0
39 #  ifndef NDEBUG
40 #    define NDEBUG
41 #  endif
42 #endif
43 
44 #include <assert.h>
45 
46 #ifdef MALLOC_TRACE
47 #include <stdio.h>
48 #include </usr/local/include/malloc.h>
49 #endif
50 /* #define TEST */
51 #include "list.h"
52 
53 /*- private data types */
54 typedef struct _lnode {
55     struct _lnode *next;
56     struct _lnode *prev;
57 
58     void *value;
59 
60 } lnode;
61 
62 struct _list {
63     lnode *head, *tail, *cptr;
64     size_t aCount;
65     list_destructor eDtor;
66 };
67 
68 /*- private methods */
69 
70 static lnode *newNode(void *el)
71 {
72     lnode *ptr = malloc(sizeof(lnode));
73     assert(ptr != 0);
74 
75     ptr->value = el;
76 
77     return ptr;
78 }
79 
80 static lnode *appendPrim(list this, void *el)
81 {
82     lnode *ptr = newNode(el);
83     lnode **flink, *blink;
84 
85     if (this->tail != 0) {
86         flink = &(this->tail->next);
87         blink = this->tail;
88     } else {
89         flink = &this->head;
90         blink = 0;
91         this->cptr = ptr;                         /*- list was empty - set current to this element */
92     }
93 
94     *flink  = ptr;
95     this->tail = ptr;
96 
97     ptr->prev = blink;
98     ptr->next = 0;
99 
100     this->aCount++;
101     return ptr;
102 }
103 #ifdef TEST
104 static lnode *prependPrim(list this, void *el)
105 {
106     lnode *ptr = newNode(el);
107     lnode *flink, **blink;
108 
109     if (this->head != 0) {
110         blink = &(this->head->prev);
111         flink = this->head;
112     } else {
113         blink = &this->tail;
114         flink = 0;
115         this->cptr  = ptr;                        /*- list was empty - set current to this element */
116     }
117 
118     *blink = ptr;
119     this->head   = ptr;
120 
121     ptr->next = flink;
122     ptr->prev = 0;
123 
124     this->aCount++;
125     return ptr;
126 }
127 #endif
128 
129 /*- public methods  */
130 list listNewEmpty(void)                           /*- default ctor */
131 {
132     list this = malloc(sizeof(struct _list));
133     assert(this != 0);
134 
135     this->aCount = 0;
136     this->eDtor = 0;
137     this->head = this->tail = this->cptr = 0;
138 
139     return this;
140 }
141 
142 #ifdef TEST
143 list listNewCopy(list l)                          /*- copy ctor */
144 {
145     lnode *ptr, *c;
146     list this;
147     assert(l != 0);
148 
149     this = malloc(sizeof(struct _list));
150     assert(this != 0);
151 
152     ptr = l->head;
153 
154     this->aCount = 0;
155     this->eDtor = 0;
156     this->head = this->tail = this->cptr = 0;
157 
158     while (ptr) {
159         c = appendPrim(this, ptr->value);
160         if (ptr == l->cptr) this->cptr = c;
161         ptr = ptr->next;
162     }
163 
164     return this;
165 }
166 #endif
167 
168 void listDispose(list this)                       /*- dtor */
169 {
170     assert(this != 0);
171     listClear(this);
172     free(this);
173 }
174 
175 void listSetElementDtor(list this, list_destructor f)
176 {
177     assert(this != 0);
178     this->eDtor = f;
179 }
180 
181 /* calling this function on an empty list is a run-time error */
182 void *listCurrent(list this)
183 {
184     assert(this != 0);
185     assert(this->cptr != 0);
186     return this->cptr->value;
187 }
188 
189 int   listCount(list this)
190 {
191     assert(this != 0);
192     return this->aCount;
193 }
194 
195 int   listIsEmpty(list this)
196 {
197     assert(this != 0);
198     return this->aCount == 0;
199 }
200 
201 
202 #ifdef TEST
203 int   listAtFirst(list this)
204 {
205     assert(this != 0);
206     return this->cptr == this->head;
207 }
208 
209 int   listAtLast(list this)
210 {
211     assert(this != 0);
212     return this->cptr == this->tail;
213 }
214 
215 int   listPosition(list this)
216 {
217     int res = 0;
218     lnode *ptr;
219     assert(this != 0);
220 
221     ptr = this->head;
222 
223     while (ptr != this->cptr) {
224         ptr = ptr->next;
225         res++;
226     }
227 
228     return res;
229 }
230 #endif
231 int    listFind(list this, void *el)
232 {
233     lnode *ptr;
234     assert(this != 0);
235 
236     ptr = this->head;
237 
238     while (ptr) {
239         if (ptr->value == el) {
240             this->cptr = ptr;
241             return 1;
242         }
243         ptr = ptr->next;
244     }
245 
246     return 0;
247 }
248 
249 int    listNext(list this)
250 {
251     return listSkipForward(this, 1);
252 }
253 
254 int    listSkipForward(list this, int n)
255 {
256     int m = 0;
257     assert(this != 0);
258 
259     if (this->cptr == 0) return 0;
260 
261     while (n != 0) {
262         if (this->cptr->next == 0) break;
263         this->cptr = this->cptr->next;
264         n--;
265         m++;
266     }
267     return m;
268 }
269 
270 int    listToFirst(list this)
271 {
272     assert(this != 0);
273 
274     if (this->cptr != this->head) {
275         this->cptr = this->head;
276         return 1;
277     }
278     return 0;
279 }
280 
281 int    listToLast(list this)
282 {
283     assert(this != 0);
284 
285     if (this->cptr != this->tail) {
286         this->cptr = this->tail;
287         return 1;
288     }
289     return 0;
290 }
291 
292 int    listPositionAt(list this, int n)                     /*- returns the actual position number */
293 {
294     int m = 0;
295     assert(this != 0);
296 
297     this->cptr = this->head;
298     while (n != 0) {
299         if (this->cptr->next == 0) break;
300         this->cptr = this->cptr->next;
301         n--;
302         m++;
303     }
304     return m;
305 }
306 
307 list   listAppend(list this, void *el)
308 {
309     assert(this != 0);
310 
311     appendPrim(this, el);
312     return this;
313 }
314 #ifdef TEST
315 list   listPrepend(list this, void *el)
316 {
317     assert(this != 0);
318 
319     prependPrim(this, el);
320     return this;
321 }
322 
323 list   listInsertAfter(list this, void *el)
324 {
325     lnode *ptr;
326     assert(this != 0);
327 
328     if (this->cptr == 0) return listAppend(this, el);
329 
330     ptr = newNode(el);
331 
332     ptr->prev  = this->cptr;
333     ptr->next  = this->cptr->next;
334     this->cptr->next = ptr;
335 
336     if (ptr->next != 0) {
337         ptr->next->prev = ptr;
338     } else {
339         this->tail = ptr;
340     }
341     this->aCount++;
342     return this;
343 }
344 
345 list   listInsertBefore(list this, void *el)
346 {
347     lnode *ptr;
348     assert(this != 0);
349 
350     if (this->cptr == 0) return listAppend(this, el);
351 
352     ptr = newNode(el);
353 
354     ptr->prev  = this->cptr->prev;
355     ptr->next  = this->cptr;
356     this->cptr->prev = ptr;
357 
358     if (ptr->prev != 0) {
359         ptr->prev->next = ptr;
360     } else {
361         this->head = ptr;
362     }
363     this->aCount++;
364     return this;
365 }
366 #endif
367 list   listRemove(list this)
368 {
369     lnode *ptr = 0;
370     if (this->cptr == 0) return this;
371 
372     if (this->cptr->next != 0) {
373         ptr  = this->cptr->next;
374         this->cptr->next->prev = this->cptr->prev;
375     } else {
376         this->tail = this->cptr->prev;
377     }
378 
379     if (this->cptr->prev != 0) {
380         if (ptr == 0) ptr = this->cptr->prev;
381         this->cptr->prev->next = this->cptr->next;
382     } else {
383         this->head = this->cptr->next;
384     }
385 
386     if (this->eDtor) this->eDtor(this->cptr->value);        /* call the dtor callback */
387 
388     free(this->cptr);
389     this->aCount--;
390     this->cptr = ptr;
391     return this;
392 }
393 
394 list   listClear(list this)
395 {
396     lnode *node = this->head, *ptr;
397 
398     while (node) {
399         ptr = node->next;
400         if (this->eDtor) this->eDtor(node->value);           /* call the dtor callback */
401         free(node);
402         this->aCount--;
403         node = ptr;
404     }
405 
406     this->head = this->tail = this->cptr = 0;
407     assert(this->aCount == 0);
408     return this;
409 }
410 
411 #ifdef TEST
412 
413 void   listForAll(list this, void (*f)(void *))
414 {
415     lnode *ptr = this->head;
416     while (ptr) {
417         f(ptr->value);
418         ptr = ptr->next;
419     }
420 }
421 
422 
423 #include <stdio.h>
424 
425 void printlist(list l)
426 {
427     int saved;
428     assert(l != 0);
429     saved = listPosition(l);
430 
431     printf("[ ");
432 
433     if (!listIsEmpty(l)) {
434         listToFirst(l);
435         do {
436             printf("%d ", (int) listCurrent(l));
437         } while (listNext(l));
438     }
439 
440     printf("]\n");
441 
442     listPositionAt(l, saved);
443 }
444 
445 void printstringlist(list l)
446 {
447     int saved;
448     assert(l != 0);
449     saved = listPosition(l);
450 
451     printf("[ ");
452 
453     if (!listIsEmpty(l)) {
454         listToFirst(l);
455         do {
456             printf("'%s' ", (char *) listCurrent(l));
457         } while (listNext(l));
458     }
459 
460     printf("]\n");
461 
462     listPositionAt(l, saved);
463 }
464 
465 void printstat(list l)
466 {
467     printf("count: %d, position: %d, isEmpty: %d, atFirst: %d, atLast: %d.\n",
468            listCount(l), listPosition(l), listIsEmpty(l), listAtFirst(l), listAtLast(l));
469 }
470 
471 void allfunc(void *e)
472 {
473     printf("%d ", e);
474 }
475 
476 void edtor(void *ptr)
477 {
478     printf("element dtor: 0x%08x\n", ptr);
479     free(ptr);
480 }
481 
482 int main()
483 {
484     list l1, l2;
485     char *ptr;
486     int i;
487 
488 #ifdef MALLOC_TRACE
489     mal_leaktrace(1);
490     mal_debug(2);
491 #endif
492 
493     l1 = listNewEmpty();
494     printstat(l1);
495 
496     listAppend(l1, 1);
497     printstat(l1);
498 
499     listAppend(l1, 2);
500     printstat(l1);
501 
502     listAppend(l1, 3);
503     printstat(l1);
504 
505     printlist(l1);
506 
507     listToFirst(l1);
508     listInsertBefore(l1, -5);
509     printlist(l1);
510 
511     l2 = listNewCopy(l1);
512     printlist(l2);
513 
514     listForAll(l2, allfunc);
515     printf("\n");
516 
517     listClear(l1);
518     listSetElementDtor(l1, edtor);
519 
520     for(i=0; i<10; i++) {
521         ptr = malloc(20);
522         snprintf(ptr, 20, "element # %d", i);
523         listAppend(l1, ptr);
524     }
525 
526     printstringlist(l1);
527 
528 
529     listDispose(l1);
530     listDispose(l2);
531 
532 #ifdef MALLOC_TRACE
533     mal_dumpleaktrace(stdout);
534 #endif
535 
536 
537     return 0;
538 }
539 #endif
540 
541 
542