0.9.0.39:
[sbcl.git] / src / runtime / util.c
1 /*
2  * miscellaneous utilities
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16 #include <stdlib.h>
17 #include "util.h"
18 \f
19 /*
20  * voidacc stuff
21  *
22  * The interface is documented in the header file.
23  *
24  * Note that we never end up needing to explicitly set errno, not even
25  * for malloc failure, because Unix98 guarantees errno=ENOMEM for us
26  * automatically in that case.
27  */
28
29 int
30 voidacc_ctor(struct voidacc *va)
31 {
32     va->n_used = 1;  /* We begin with 1 entry already for zero termination. */
33     va->n_avail = 4; /* arbitrary initial value */
34     va->result = (void**)calloc(sizeof(void*), va->n_avail);
35     return va->result ? 0 : (-1);
36 }
37
38 int
39 voidacc_acc(struct voidacc *va, void* x)
40 {
41     /* Ensure that we have enough space, or die. */
42     if (va->n_used >= va->n_avail) { /* if we've run out of space */
43         /* We need to allocate more space. */
44         int new_n_avail = 1 + 2 * va->n_avail;
45         void** new_result = (void**)calloc(sizeof(void*), new_n_avail);
46         int i;
47         if (!new_result) {
48             return 1;
49         }
50         /* Copy old result into new space. */
51         for (i = va->n_used; --i >= 0; ) {
52             new_result[i] = va->result[i];
53         }
54         free(va->result);
55         va->result = new_result;
56         va->n_avail = new_n_avail;
57     }
58
59     /* If we get to this point, we have enough space to store x. 
60      *  
61      * Note that since we cleverly counted the 0 as part of the space
62      * used, now we need to subtract one to get the correct offset to
63      * write into.:-| */
64     va->result[va->n_used++ - 1] = x;
65     return 0;
66 }
67
68 void**
69 voidacc_give_away_result(struct voidacc *va)
70 {
71     /* (We could do realloc(3) here to try to shrink the result down
72      * to minimum size, but that's not really needed for the
73      * directory-iteration application this was originally written
74      * for, so for now we just do the simplest thing which could
75      * possibly work.) */
76     void **result_tmp = va->result;
77     va->result = 0;
78     return result_tmp;
79 }
80
81 void
82 voidacc_dtor(struct voidacc *va)
83 {
84     /* if result has been allocated and hasn't been given away */
85     if (va->result) {
86         free(voidacc_give_away_result(va));
87     }
88 }