- implemented -Wsign-compare
[cparser] / adt / array.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       Array --- dynamic & flexible arrays.
23  * @author      Markus Armbruster
24  * @version     $Id$
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_STDLIB_H
32 # include <stdlib.h>
33 #endif
34
35 #include "array.h"
36 #include "xmalloc.h"
37
38 /* Undefine the macros to get the functions instead, cf tmalloc.c.  */
39 #undef xmalloc
40 #undef xrealloc
41 #undef xstrdup
42 #undef xfree
43
44 #ifndef MAX
45 # define MAX(a,b) ((a) > (b) ? (a) : (b))
46 #endif
47 #ifndef MIN
48 # define MIN(a,b) ((a) > (b) ? (b) : (a))
49 #endif
50
51 /**
52  * An empty dynamic array
53  */
54 _arr_descr arr_mt_descr;
55
56 /**
57  * Creates a dynamic array on a obstack.
58  *
59  * @param obstack    An struct obstack * were the data will be allocated
60  * @param nelts      The number of elements
61  * @param elts_size  The size of the array elements.
62  *
63  * @return A pointer to the dynamic array (can be used as a pointer to the
64  *         first element of this array).
65  *
66  * @remark Helper function, use NEW_ARR_D() instead.
67  */
68 void *
69 _new_arr_d (struct obstack *obstack, int nelts, size_t elts_size)
70 {
71   _arr_descr *new;
72
73   assert (obstack && (nelts >= 0));
74
75   new = obstack_alloc (obstack, _ARR_ELTS_OFFS+elts_size);
76   _ARR_SET_DBGINF (new, ARR_D_MAGIC, elts_size/nelts);
77   new->u.obstack = obstack;
78   new->nelts = nelts;
79   return new->v.elts;
80 }
81
82 /**
83  * Creates a flexible array.
84  *
85  * @param nelts      The number of elements
86  * @param elts_size  The size of the array elements.
87  *
88  * @return A pointer to the flexible array (can be used as a pointer to the
89  *         first element of this array).
90  *
91  * @remark Helper function, use NEW_ARR_F() instead.
92  */
93 void *
94 _new_arr_f (int nelts, size_t elts_size)
95 {
96   _arr_descr *new;
97
98   assert (nelts >= 0);
99   new = xmalloc (_ARR_ELTS_OFFS+elts_size);
100   _ARR_SET_DBGINF (new, ARR_F_MAGIC, nelts ? elts_size/nelts : 0);
101   new->u.allocated = new->nelts = nelts;
102   return new->v.elts;
103 }
104
105 /**
106  * Delete a flexible array.
107  *
108  * @param elts    The flexible array (pointer to the first element).
109  *
110  * @remark Helper function, use DEL_ARR_F() instead.
111  */
112 void
113 _del_arr_f (void *elts)
114 {
115   _arr_descr *dp = _ARR_DESCR (elts);
116
117   ARR_VRFY (elts);
118   assert (dp->magic == ARR_F_MAGIC);
119
120 #ifndef NDEBUG
121   dp->magic = 0xdeadbeef;
122 #endif
123   free (dp);
124 }
125
126 /**
127  * Resize a flexible array, always reallocate data.
128  *
129  * @param elts       The flexible array (pointer to the first element).
130  * @param nelts      The new number of elements.
131  * @param elts_size  The size of the array elements.
132  *
133  * @return A resized flexible array, possibly other address than
134  *         elts.
135  *
136  * @remark Helper function, use ARR_SETLEN() instead.
137  */
138 void *
139 _arr_setlen (void *elts, int nelts, size_t elts_size)
140 {
141   _arr_descr *dp = _ARR_DESCR (elts);
142
143   assert ((dp->magic == ARR_F_MAGIC) && (nelts >= 0));
144   ARR_VRFY (elts);
145   assert (!dp->eltsize || !nelts || (dp->eltsize == elts_size/nelts));
146
147   dp = xrealloc (dp, _ARR_ELTS_OFFS+elts_size);
148   dp->u.allocated = dp->nelts = nelts;
149
150   return dp->v.elts;
151 }
152
153 /**
154  * Resize a flexible array, allocate more data if needed but do NOT
155  * reduce.
156  *
157  * @param elts     The flexible array (pointer to the first element).
158  * @param nelts    The new number of elements.
159  * @param eltsize  The size of the array elements.
160  *
161  * @return A resized flexible array, possibly other address than
162  *         elts.
163  *
164  * @remark Helper function, use ARR_RESIZE() instead.
165  */
166 void *
167 _arr_resize (void *elts, int nelts, size_t eltsize)
168 {
169   _arr_descr *dp = _ARR_DESCR (elts);
170   int n;
171
172   assert ((dp->magic == ARR_F_MAGIC) && (nelts >= 0));
173   ARR_VRFY (elts);
174   assert (dp->eltsize ? dp->eltsize == eltsize : (dp->eltsize = eltsize, 1));
175
176   /* @@@ lots of resizes for small nelts */
177   n = MAX (1, dp->u.allocated);
178   while (nelts > n) n <<= 1;
179   while (3*nelts < n) n >>= 1;
180   assert (n >= nelts);
181
182   if (n != dp->u.allocated) {
183     dp = xrealloc (dp, _ARR_ELTS_OFFS+eltsize*n);
184     dp->u.allocated = n;
185 #if defined(DEBUG) && defined(HAVE_GNU_MALLOC)
186   } else {
187     tmalloc_tag = NULL;
188 #endif
189   }
190   dp->nelts = nelts;
191
192   return dp->v.elts;
193 }
194
195 #ifdef DEBUG_libfirm
196 /**
197  * This function returns the length of a flexible array.
198  * Do NOT use is in code, use ARR_LEN() macro!
199  * This function is intended to be called from a debugger.
200  */
201 int array_len(void *arr) {
202   return ARR_LEN(arr);
203 }
204
205 /**
206  * This function returns the array descriptor of a flexible array.
207  * Do NOT use is in code!.
208  * This function is intended to be called from a debugger.
209  */
210 _arr_descr *array_descr(void *arr) {
211   if (! arr)
212     return NULL;
213   return _ARR_DESCR(arr);
214 }
215 #endif /* DEBUG_libfirm */