]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/vec.h
Copyright updates for 2007.
[thirdparty/binutils-gdb.git] / gdb / vec.h
1 /* Vector API for GDB.
2 Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22 #if !defined (GDB_VEC_H)
23 #define GDB_VEC_H
24
25 #include <stddef.h>
26 #include "gdb_string.h"
27 #include "gdb_assert.h"
28
29 /* The macros here implement a set of templated vector types and
30 associated interfaces. These templates are implemented with
31 macros, as we're not in C++ land. The interface functions are
32 typesafe and use static inline functions, sometimes backed by
33 out-of-line generic functions.
34
35 Because of the different behavior of structure objects, scalar
36 objects and of pointers, there are three flavors, one for each of
37 these variants. Both the structure object and pointer variants
38 pass pointers to objects around -- in the former case the pointers
39 are stored into the vector and in the latter case the pointers are
40 dereferenced and the objects copied into the vector. The scalar
41 object variant is suitable for int-like objects, and the vector
42 elements are returned by value.
43
44 There are both 'index' and 'iterate' accessors. The iterator
45 returns a boolean iteration condition and updates the iteration
46 variable passed by reference. Because the iterator will be
47 inlined, the address-of can be optimized away.
48
49 The vectors are implemented using the trailing array idiom, thus
50 they are not resizeable without changing the address of the vector
51 object itself. This means you cannot have variables or fields of
52 vector type -- always use a pointer to a vector. The one exception
53 is the final field of a structure, which could be a vector type.
54 You will have to use the embedded_size & embedded_init calls to
55 create such objects, and they will probably not be resizeable (so
56 don't use the 'safe' allocation variants). The trailing array
57 idiom is used (rather than a pointer to an array of data), because,
58 if we allow NULL to also represent an empty vector, empty vectors
59 occupy minimal space in the structure containing them.
60
61 Each operation that increases the number of active elements is
62 available in 'quick' and 'safe' variants. The former presumes that
63 there is sufficient allocated space for the operation to succeed
64 (it dies if there is not). The latter will reallocate the
65 vector, if needed. Reallocation causes an exponential increase in
66 vector size. If you know you will be adding N elements, it would
67 be more efficient to use the reserve operation before adding the
68 elements with the 'quick' operation. This will ensure there are at
69 least as many elements as you ask for, it will exponentially
70 increase if there are too few spare slots. If you want reserve a
71 specific number of slots, but do not want the exponential increase
72 (for instance, you know this is the last allocation), use a
73 negative number for reservation. You can also create a vector of a
74 specific size from the get go.
75
76 You should prefer the push and pop operations, as they append and
77 remove from the end of the vector. If you need to remove several
78 items in one go, use the truncate operation. The insert and remove
79 operations allow you to change elements in the middle of the
80 vector. There are two remove operations, one which preserves the
81 element ordering 'ordered_remove', and one which does not
82 'unordered_remove'. The latter function copies the end element
83 into the removed slot, rather than invoke a memmove operation. The
84 'lower_bound' function will determine where to place an item in the
85 array using insert that will maintain sorted order.
86
87 If you need to directly manipulate a vector, then the 'address'
88 accessor will return the address of the start of the vector. Also
89 the 'space' predicate will tell you whether there is spare capacity
90 in the vector. You will not normally need to use these two functions.
91
92 Vector types are defined using a DEF_VEC_{O,P,I}(TYPEDEF) macro.
93 Variables of vector type are declared using a VEC(TYPEDEF) macro.
94 The characters O, P and I indicate whether TYPEDEF is a pointer
95 (P), object (O) or integral (I) type. Be careful to pick the
96 correct one, as you'll get an awkward and inefficient API if you
97 use the wrong one. There is a check, which results in a
98 compile-time warning, for the P and I versions, but there is no
99 check for the O versions, as that is not possible in plain C.
100
101 An example of their use would be,
102
103 DEF_VEC_P(tree); // non-managed tree vector.
104
105 struct my_struct {
106 VEC(tree) *v; // A (pointer to) a vector of tree pointers.
107 };
108
109 struct my_struct *s;
110
111 if (VEC_length(tree, s->v)) { we have some contents }
112 VEC_safe_push(tree, s->v, decl); // append some decl onto the end
113 for (ix = 0; VEC_iterate(tree, s->v, ix, elt); ix++)
114 { do something with elt }
115
116 */
117
118 /* Macros to invoke API calls. A single macro works for both pointer
119 and object vectors, but the argument and return types might well be
120 different. In each macro, T is the typedef of the vector elements.
121 Some of these macros pass the vector, V, by reference (by taking
122 its address), this is noted in the descriptions. */
123
124 /* Length of vector
125 unsigned VEC_T_length(const VEC(T) *v);
126
127 Return the number of active elements in V. V can be NULL, in which
128 case zero is returned. */
129
130 #define VEC_length(T,V) (VEC_OP(T,length)(V))
131
132
133 /* Check if vector is empty
134 int VEC_T_empty(const VEC(T) *v);
135
136 Return nonzero if V is an empty vector (or V is NULL), zero otherwise. */
137
138 #define VEC_empty(T,V) (VEC_length (T,V) == 0)
139
140
141 /* Get the final element of the vector.
142 T VEC_T_last(VEC(T) *v); // Integer
143 T VEC_T_last(VEC(T) *v); // Pointer
144 T *VEC_T_last(VEC(T) *v); // Object
145
146 Return the final element. V must not be empty. */
147
148 #define VEC_last(T,V) (VEC_OP(T,last)(V VEC_ASSERT_INFO))
149
150 /* Index into vector
151 T VEC_T_index(VEC(T) *v, unsigned ix); // Integer
152 T VEC_T_index(VEC(T) *v, unsigned ix); // Pointer
153 T *VEC_T_index(VEC(T) *v, unsigned ix); // Object
154
155 Return the IX'th element. If IX must be in the domain of V. */
156
157 #define VEC_index(T,V,I) (VEC_OP(T,index)(V,I VEC_ASSERT_INFO))
158
159 /* Iterate over vector
160 int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Integer
161 int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Pointer
162 int VEC_T_iterate(VEC(T) *v, unsigned ix, T *&ptr); // Object
163
164 Return iteration condition and update PTR to point to the IX'th
165 element. At the end of iteration, sets PTR to NULL. Use this to
166 iterate over the elements of a vector as follows,
167
168 for (ix = 0; VEC_iterate(T,v,ix,ptr); ix++)
169 continue; */
170
171 #define VEC_iterate(T,V,I,P) (VEC_OP(T,iterate)(V,I,&(P)))
172
173 /* Allocate new vector.
174 VEC(T,A) *VEC_T_alloc(int reserve);
175
176 Allocate a new vector with space for RESERVE objects. If RESERVE
177 is zero, NO vector is created. */
178
179 #define VEC_alloc(T,N) (VEC_OP(T,alloc)(N))
180
181 /* Free a vector.
182 void VEC_T_free(VEC(T,A) *&);
183
184 Free a vector and set it to NULL. */
185
186 #define VEC_free(T,V) (VEC_OP(T,free)(&V))
187
188 /* Use these to determine the required size and initialization of a
189 vector embedded within another structure (as the final member).
190
191 size_t VEC_T_embedded_size(int reserve);
192 void VEC_T_embedded_init(VEC(T) *v, int reserve);
193
194 These allow the caller to perform the memory allocation. */
195
196 #define VEC_embedded_size(T,N) (VEC_OP(T,embedded_size)(N))
197 #define VEC_embedded_init(T,O,N) (VEC_OP(T,embedded_init)(VEC_BASE(O),N))
198
199 /* Copy a vector.
200 VEC(T,A) *VEC_T_copy(VEC(T) *);
201
202 Copy the live elements of a vector into a new vector. The new and
203 old vectors need not be allocated by the same mechanism. */
204
205 #define VEC_copy(T,V) (VEC_OP(T,copy)(V))
206
207 /* Determine if a vector has additional capacity.
208
209 int VEC_T_space (VEC(T) *v,int reserve)
210
211 If V has space for RESERVE additional entries, return nonzero. You
212 usually only need to use this if you are doing your own vector
213 reallocation, for instance on an embedded vector. This returns
214 nonzero in exactly the same circumstances that VEC_T_reserve
215 will. */
216
217 #define VEC_space(T,V,R) (VEC_OP(T,space)(V,R VEC_ASSERT_INFO))
218
219 /* Reserve space.
220 int VEC_T_reserve(VEC(T,A) *&v, int reserve);
221
222 Ensure that V has at least abs(RESERVE) slots available. The
223 signedness of RESERVE determines the reallocation behavior. A
224 negative value will not create additional headroom beyond that
225 requested. A positive value will create additional headroom. Note
226 this can cause V to be reallocated. Returns nonzero iff
227 reallocation actually occurred. */
228
229 #define VEC_reserve(T,V,R) (VEC_OP(T,reserve)(&(V),R VEC_ASSERT_INFO))
230
231 /* Push object with no reallocation
232 T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer
233 T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
234 T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
235
236 Push a new element onto the end, returns a pointer to the slot
237 filled in. For object vectors, the new value can be NULL, in which
238 case NO initialization is performed. There must
239 be sufficient space in the vector. */
240
241 #define VEC_quick_push(T,V,O) (VEC_OP(T,quick_push)(V,O VEC_ASSERT_INFO))
242
243 /* Push object with reallocation
244 T *VEC_T_safe_push (VEC(T,A) *&v, T obj); // Integer
245 T *VEC_T_safe_push (VEC(T,A) *&v, T obj); // Pointer
246 T *VEC_T_safe_push (VEC(T,A) *&v, T *obj); // Object
247
248 Push a new element onto the end, returns a pointer to the slot
249 filled in. For object vectors, the new value can be NULL, in which
250 case NO initialization is performed. Reallocates V, if needed. */
251
252 #define VEC_safe_push(T,V,O) (VEC_OP(T,safe_push)(&(V),O VEC_ASSERT_INFO))
253
254 /* Pop element off end
255 T VEC_T_pop (VEC(T) *v); // Integer
256 T VEC_T_pop (VEC(T) *v); // Pointer
257 void VEC_T_pop (VEC(T) *v); // Object
258
259 Pop the last element off the end. Returns the element popped, for
260 pointer vectors. */
261
262 #define VEC_pop(T,V) (VEC_OP(T,pop)(V VEC_ASSERT_INFO))
263
264 /* Truncate to specific length
265 void VEC_T_truncate (VEC(T) *v, unsigned len);
266
267 Set the length as specified. The new length must be less than or
268 equal to the current length. This is an O(1) operation. */
269
270 #define VEC_truncate(T,V,I) \
271 (VEC_OP(T,truncate)(V,I VEC_ASSERT_INFO))
272
273 /* Grow to a specific length.
274 void VEC_T_safe_grow (VEC(T,A) *&v, int len);
275
276 Grow the vector to a specific length. The LEN must be as
277 long or longer than the current length. The new elements are
278 uninitialized. */
279
280 #define VEC_safe_grow(T,V,I) \
281 (VEC_OP(T,safe_grow)(&(V),I VEC_ASSERT_INFO))
282
283 /* Replace element
284 T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Integer
285 T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Pointer
286 T *VEC_T_replace (VEC(T) *v, unsigned ix, T *val); // Object
287
288 Replace the IXth element of V with a new value, VAL. For pointer
289 vectors returns the original value. For object vectors returns a
290 pointer to the new value. For object vectors the new value can be
291 NULL, in which case no overwriting of the slot is actually
292 performed. */
293
294 #define VEC_replace(T,V,I,O) (VEC_OP(T,replace)(V,I,O VEC_ASSERT_INFO))
295
296 /* Insert object with no reallocation
297 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Integer
298 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer
299 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object
300
301 Insert an element, VAL, at the IXth position of V. Return a pointer
302 to the slot created. For vectors of object, the new value can be
303 NULL, in which case no initialization of the inserted slot takes
304 place. There must be sufficient space. */
305
306 #define VEC_quick_insert(T,V,I,O) \
307 (VEC_OP(T,quick_insert)(V,I,O VEC_ASSERT_INFO))
308
309 /* Insert object with reallocation
310 T *VEC_T_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Integer
311 T *VEC_T_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Pointer
312 T *VEC_T_safe_insert (VEC(T,A) *&v, unsigned ix, T *val); // Object
313
314 Insert an element, VAL, at the IXth position of V. Return a pointer
315 to the slot created. For vectors of object, the new value can be
316 NULL, in which case no initialization of the inserted slot takes
317 place. Reallocate V, if necessary. */
318
319 #define VEC_safe_insert(T,V,I,O) \
320 (VEC_OP(T,safe_insert)(&(V),I,O VEC_ASSERT_INFO))
321
322 /* Remove element retaining order
323 T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Integer
324 T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer
325 void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Object
326
327 Remove an element from the IXth position of V. Ordering of
328 remaining elements is preserved. For pointer vectors returns the
329 removed object. This is an O(N) operation due to a memmove. */
330
331 #define VEC_ordered_remove(T,V,I) \
332 (VEC_OP(T,ordered_remove)(V,I VEC_ASSERT_INFO))
333
334 /* Remove element destroying order
335 T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Integer
336 T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer
337 void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Object
338
339 Remove an element from the IXth position of V. Ordering of
340 remaining elements is destroyed. For pointer vectors returns the
341 removed object. This is an O(1) operation. */
342
343 #define VEC_unordered_remove(T,V,I) \
344 (VEC_OP(T,unordered_remove)(V,I VEC_ASSERT_INFO))
345
346 /* Remove a block of elements
347 void VEC_T_block_remove (VEC(T) *v, unsigned ix, unsigned len);
348
349 Remove LEN elements starting at the IXth. Ordering is retained.
350 This is an O(1) operation. */
351
352 #define VEC_block_remove(T,V,I,L) \
353 (VEC_OP(T,block_remove)(V,I,L) VEC_ASSERT_INFO)
354
355 /* Get the address of the array of elements
356 T *VEC_T_address (VEC(T) v)
357
358 If you need to directly manipulate the array (for instance, you
359 want to feed it to qsort), use this accessor. */
360
361 #define VEC_address(T,V) (VEC_OP(T,address)(V))
362
363 /* Find the first index in the vector not less than the object.
364 unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
365 int (*lessthan) (const T, const T)); // Integer
366 unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
367 int (*lessthan) (const T, const T)); // Pointer
368 unsigned VEC_T_lower_bound (VEC(T) *v, const T *val,
369 int (*lessthan) (const T*, const T*)); // Object
370
371 Find the first position in which VAL could be inserted without
372 changing the ordering of V. LESSTHAN is a function that returns
373 true if the first argument is strictly less than the second. */
374
375 #define VEC_lower_bound(T,V,O,LT) \
376 (VEC_OP(T,lower_bound)(V,O,LT VEC_ASSERT_INFO))
377
378 /* Reallocate an array of elements with prefix. */
379 extern void *vec_p_reserve (void *, int);
380 extern void *vec_o_reserve (void *, int, size_t, size_t);
381 #define vec_free(V) xfree (V)
382
383 #define VEC_ASSERT_INFO ,__FILE__,__LINE__
384 #define VEC_ASSERT_DECL ,const char *file_,unsigned line_
385 #define VEC_ASSERT_PASS ,file_,line_
386 #define vec_assert(expr, op) \
387 ((void)((expr) ? 0 : (gdb_assert_fail (op, file_, line_, ASSERT_FUNCTION), 0)))
388
389 #define VEC(T) VEC_##T
390 #define VEC_OP(T,OP) VEC_##T##_##OP
391
392 #define VEC_T(T) \
393 typedef struct VEC(T) \
394 { \
395 unsigned num; \
396 unsigned alloc; \
397 T vec[1]; \
398 } VEC(T)
399
400 /* Vector of integer-like object. */
401 #define DEF_VEC_I(T) \
402 static inline void VEC_OP (T,must_be_integral_type) (void) \
403 { \
404 (void)~(T)0; \
405 } \
406 \
407 VEC_T(T); \
408 DEF_VEC_FUNC_P(T) \
409 DEF_VEC_ALLOC_FUNC_I(T) \
410 struct vec_swallow_trailing_semi
411
412 /* Vector of pointer to object. */
413 #define DEF_VEC_P(T) \
414 static inline void VEC_OP (T,must_be_pointer_type) (void) \
415 { \
416 (void)((T)1 == (void *)1); \
417 } \
418 \
419 VEC_T(T); \
420 DEF_VEC_FUNC_P(T) \
421 DEF_VEC_ALLOC_FUNC_P(T) \
422 struct vec_swallow_trailing_semi
423
424 /* Vector of object. */
425 #define DEF_VEC_O(T) \
426 VEC_T(T); \
427 DEF_VEC_FUNC_O(T) \
428 DEF_VEC_ALLOC_FUNC_O(T) \
429 struct vec_swallow_trailing_semi
430
431 #define DEF_VEC_ALLOC_FUNC_I(T) \
432 static inline VEC(T) *VEC_OP (T,alloc) \
433 (int alloc_) \
434 { \
435 /* We must request exact size allocation, hence the negation. */ \
436 return (VEC(T) *) vec_o_reserve (NULL, -alloc_, \
437 offsetof (VEC(T),vec), sizeof (T)); \
438 } \
439 \
440 static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_) \
441 { \
442 size_t len_ = vec_ ? vec_->num : 0; \
443 VEC (T) *new_vec_ = NULL; \
444 \
445 if (len_) \
446 { \
447 /* We must request exact size allocation, hence the negation. */ \
448 new_vec_ = (VEC (T) *) \
449 vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T)); \
450 \
451 new_vec_->num = len_; \
452 memcpy (new_vec_->vec, vec_->vec, sizeof (T) * len_); \
453 } \
454 return new_vec_; \
455 } \
456 \
457 static inline void VEC_OP (T,free) \
458 (VEC(T) **vec_) \
459 { \
460 if (*vec_) \
461 vec_free (*vec_); \
462 *vec_ = NULL; \
463 } \
464 \
465 static inline int VEC_OP (T,reserve) \
466 (VEC(T) **vec_, int alloc_ VEC_ASSERT_DECL) \
467 { \
468 int extend = !VEC_OP (T,space) \
469 (*vec_, alloc_ < 0 ? -alloc_ : alloc_ VEC_ASSERT_PASS); \
470 \
471 if (extend) \
472 *vec_ = (VEC(T) *) vec_o_reserve (*vec_, alloc_, \
473 offsetof (VEC(T),vec), sizeof (T)); \
474 \
475 return extend; \
476 } \
477 \
478 static inline void VEC_OP (T,safe_grow) \
479 (VEC(T) **vec_, int size_ VEC_ASSERT_DECL) \
480 { \
481 vec_assert (size_ >= 0 && VEC_OP(T,length) (*vec_) <= (unsigned)size_, \
482 "safe_grow"); \
483 VEC_OP (T,reserve) (vec_, (int)(*vec_ ? (*vec_)->num : 0) - size_ \
484 VEC_ASSERT_PASS); \
485 (*vec_)->num = size_; \
486 } \
487 \
488 static inline T *VEC_OP (T,safe_push) \
489 (VEC(T) **vec_, const T obj_ VEC_ASSERT_DECL) \
490 { \
491 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
492 \
493 return VEC_OP (T,quick_push) (*vec_, obj_ VEC_ASSERT_PASS); \
494 } \
495 \
496 static inline T *VEC_OP (T,safe_insert) \
497 (VEC(T) **vec_, unsigned ix_, const T obj_ VEC_ASSERT_DECL) \
498 { \
499 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
500 \
501 return VEC_OP (T,quick_insert) (*vec_, ix_, obj_ VEC_ASSERT_PASS); \
502 }
503
504 #define DEF_VEC_FUNC_P(T) \
505 static inline unsigned VEC_OP (T,length) (const VEC(T) *vec_) \
506 { \
507 return vec_ ? vec_->num : 0; \
508 } \
509 \
510 static inline T VEC_OP (T,last) \
511 (const VEC(T) *vec_ VEC_ASSERT_DECL) \
512 { \
513 vec_assert (vec_ && vec_->num, "last"); \
514 \
515 return vec_->vec[vec_->num - 1]; \
516 } \
517 \
518 static inline T VEC_OP (T,index) \
519 (const VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
520 { \
521 vec_assert (vec_ && ix_ < vec_->num, "index"); \
522 \
523 return vec_->vec[ix_]; \
524 } \
525 \
526 static inline int VEC_OP (T,iterate) \
527 (const VEC(T) *vec_, unsigned ix_, T *ptr) \
528 { \
529 if (vec_ && ix_ < vec_->num) \
530 { \
531 *ptr = vec_->vec[ix_]; \
532 return 1; \
533 } \
534 else \
535 { \
536 *ptr = 0; \
537 return 0; \
538 } \
539 } \
540 \
541 static inline size_t VEC_OP (T,embedded_size) \
542 (int alloc_) \
543 { \
544 return offsetof (VEC(T),vec) + alloc_ * sizeof(T); \
545 } \
546 \
547 static inline void VEC_OP (T,embedded_init) \
548 (VEC(T) *vec_, int alloc_) \
549 { \
550 vec_->num = 0; \
551 vec_->alloc = alloc_; \
552 } \
553 \
554 static inline int VEC_OP (T,space) \
555 (VEC(T) *vec_, int alloc_ VEC_ASSERT_DECL) \
556 { \
557 vec_assert (alloc_ >= 0, "space"); \
558 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
559 } \
560 \
561 static inline T *VEC_OP (T,quick_push) \
562 (VEC(T) *vec_, T obj_ VEC_ASSERT_DECL) \
563 { \
564 T *slot_; \
565 \
566 vec_assert (vec_->num < vec_->alloc, "quick_push"); \
567 slot_ = &vec_->vec[vec_->num++]; \
568 *slot_ = obj_; \
569 \
570 return slot_; \
571 } \
572 \
573 static inline T VEC_OP (T,pop) (VEC(T) *vec_ VEC_ASSERT_DECL) \
574 { \
575 T obj_; \
576 \
577 vec_assert (vec_->num, "pop"); \
578 obj_ = vec_->vec[--vec_->num]; \
579 \
580 return obj_; \
581 } \
582 \
583 static inline void VEC_OP (T,truncate) \
584 (VEC(T) *vec_, unsigned size_ VEC_ASSERT_DECL) \
585 { \
586 vec_assert (vec_ ? vec_->num >= size_ : !size_, "truncate"); \
587 if (vec_) \
588 vec_->num = size_; \
589 } \
590 \
591 static inline T VEC_OP (T,replace) \
592 (VEC(T) *vec_, unsigned ix_, T obj_ VEC_ASSERT_DECL) \
593 { \
594 T old_obj_; \
595 \
596 vec_assert (ix_ < vec_->num, "replace"); \
597 old_obj_ = vec_->vec[ix_]; \
598 vec_->vec[ix_] = obj_; \
599 \
600 return old_obj_; \
601 } \
602 \
603 static inline T *VEC_OP (T,quick_insert) \
604 (VEC(T) *vec_, unsigned ix_, T obj_ VEC_ASSERT_DECL) \
605 { \
606 T *slot_; \
607 \
608 vec_assert (vec_->num < vec_->alloc && ix_ <= vec_->num, "quick_insert"); \
609 slot_ = &vec_->vec[ix_]; \
610 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
611 *slot_ = obj_; \
612 \
613 return slot_; \
614 } \
615 \
616 static inline T VEC_OP (T,ordered_remove) \
617 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
618 { \
619 T *slot_; \
620 T obj_; \
621 \
622 vec_assert (ix_ < vec_->num, "ordered_remove"); \
623 slot_ = &vec_->vec[ix_]; \
624 obj_ = *slot_; \
625 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
626 \
627 return obj_; \
628 } \
629 \
630 static inline T VEC_OP (T,unordered_remove) \
631 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
632 { \
633 T *slot_; \
634 T obj_; \
635 \
636 vec_assert (ix_ < vec_->num, "unordered_remove"); \
637 slot_ = &vec_->vec[ix_]; \
638 obj_ = *slot_; \
639 *slot_ = vec_->vec[--vec_->num]; \
640 \
641 return obj_; \
642 } \
643 \
644 static inline void VEC_OP (T,block_remove) \
645 (VEC(T) *vec_, unsigned ix_, unsigned len_ VEC_ASSERT_DECL) \
646 { \
647 T *slot_; \
648 \
649 vec_assert (ix_ + len_ <= vec_->num, "block_remove"); \
650 slot_ = &vec_->vec[ix_]; \
651 vec_->num -= len_; \
652 memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
653 } \
654 \
655 static inline T *VEC_OP (T,address) \
656 (VEC(T) *vec_) \
657 { \
658 return vec_ ? vec_->vec : 0; \
659 } \
660 \
661 static inline unsigned VEC_OP (T,lower_bound) \
662 (VEC(T) *vec_, const T obj_, \
663 int (*lessthan_)(const T, const T) VEC_ASSERT_DECL) \
664 { \
665 unsigned int len_ = VEC_OP (T, length) (vec_); \
666 unsigned int half_, middle_; \
667 unsigned int first_ = 0; \
668 while (len_ > 0) \
669 { \
670 T middle_elem_; \
671 half_ = len_ >> 1; \
672 middle_ = first_; \
673 middle_ += half_; \
674 middle_elem_ = VEC_OP (T,index) (vec_, middle_ VEC_ASSERT_PASS); \
675 if (lessthan_ (middle_elem_, obj_)) \
676 { \
677 first_ = middle_; \
678 ++first_; \
679 len_ = len_ - half_ - 1; \
680 } \
681 else \
682 len_ = half_; \
683 } \
684 return first_; \
685 }
686
687 #define DEF_VEC_ALLOC_FUNC_P(T) \
688 static inline VEC(T) *VEC_OP (T,alloc) \
689 (int alloc_) \
690 { \
691 /* We must request exact size allocation, hence the negation. */ \
692 return (VEC(T) *) vec_p_reserve (NULL, -alloc_); \
693 } \
694 \
695 static inline void VEC_OP (T,free) \
696 (VEC(T) **vec_) \
697 { \
698 if (*vec_) \
699 vec_free (*vec_); \
700 *vec_ = NULL; \
701 } \
702 \
703 static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_) \
704 { \
705 size_t len_ = vec_ ? vec_->num : 0; \
706 VEC (T) *new_vec_ = NULL; \
707 \
708 if (len_) \
709 { \
710 /* We must request exact size allocation, hence the negation. */ \
711 new_vec_ = (VEC (T) *)(vec_p_reserve (NULL, -len_)); \
712 \
713 new_vec_->num = len_; \
714 memcpy (new_vec_->vec, vec_->vec, sizeof (T) * len_); \
715 } \
716 return new_vec_; \
717 } \
718 \
719 static inline int VEC_OP (T,reserve) \
720 (VEC(T) **vec_, int alloc_ VEC_ASSERT_DECL) \
721 { \
722 int extend = !VEC_OP (T,space) \
723 (*vec_, alloc_ < 0 ? -alloc_ : alloc_ VEC_ASSERT_PASS); \
724 \
725 if (extend) \
726 *vec_ = (VEC(T) *) vec_p_reserve (*vec_, alloc_); \
727 \
728 return extend; \
729 } \
730 \
731 static inline void VEC_OP (T,safe_grow) \
732 (VEC(T) **vec_, int size_ VEC_ASSERT_DECL) \
733 { \
734 vec_assert (size_ >= 0 && VEC_OP(T,length) (*vec_) <= (unsigned)size_, \
735 "safe_grow"); \
736 VEC_OP (T,reserve) \
737 (vec_, (int)(*vec_ ? (*vec_)->num : 0) - size_ VEC_ASSERT_PASS); \
738 (*vec_)->num = size_; \
739 } \
740 \
741 static inline T *VEC_OP (T,safe_push) \
742 (VEC(T) **vec_, T obj_ VEC_ASSERT_DECL) \
743 { \
744 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
745 \
746 return VEC_OP (T,quick_push) (*vec_, obj_ VEC_ASSERT_PASS); \
747 } \
748 \
749 static inline T *VEC_OP (T,safe_insert) \
750 (VEC(T) **vec_, unsigned ix_, T obj_ VEC_ASSERT_DECL) \
751 { \
752 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
753 \
754 return VEC_OP (T,quick_insert) (*vec_, ix_, obj_ VEC_ASSERT_PASS); \
755 }
756
757 #define DEF_VEC_FUNC_O(T) \
758 static inline unsigned VEC_OP (T,length) (const VEC(T) *vec_) \
759 { \
760 return vec_ ? vec_->num : 0; \
761 } \
762 \
763 static inline T *VEC_OP (T,last) (VEC(T) *vec_ VEC_ASSERT_DECL) \
764 { \
765 vec_assert (vec_ && vec_->num, "last"); \
766 \
767 return &vec_->vec[vec_->num - 1]; \
768 } \
769 \
770 static inline T *VEC_OP (T,index) \
771 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
772 { \
773 vec_assert (vec_ && ix_ < vec_->num, "index"); \
774 \
775 return &vec_->vec[ix_]; \
776 } \
777 \
778 static inline int VEC_OP (T,iterate) \
779 (VEC(T) *vec_, unsigned ix_, T **ptr) \
780 { \
781 if (vec_ && ix_ < vec_->num) \
782 { \
783 *ptr = &vec_->vec[ix_]; \
784 return 1; \
785 } \
786 else \
787 { \
788 *ptr = 0; \
789 return 0; \
790 } \
791 } \
792 \
793 static inline size_t VEC_OP (T,embedded_size) \
794 (int alloc_) \
795 { \
796 return offsetof (VEC(T),vec) + alloc_ * sizeof(T); \
797 } \
798 \
799 static inline void VEC_OP (T,embedded_init) \
800 (VEC(T) *vec_, int alloc_) \
801 { \
802 vec_->num = 0; \
803 vec_->alloc = alloc_; \
804 } \
805 \
806 static inline int VEC_OP (T,space) \
807 (VEC(T) *vec_, int alloc_ VEC_ASSERT_DECL) \
808 { \
809 vec_assert (alloc_ >= 0, "space"); \
810 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
811 } \
812 \
813 static inline T *VEC_OP (T,quick_push) \
814 (VEC(T) *vec_, const T *obj_ VEC_ASSERT_DECL) \
815 { \
816 T *slot_; \
817 \
818 vec_assert (vec_->num < vec_->alloc, "quick_push"); \
819 slot_ = &vec_->vec[vec_->num++]; \
820 if (obj_) \
821 *slot_ = *obj_; \
822 \
823 return slot_; \
824 } \
825 \
826 static inline void VEC_OP (T,pop) (VEC(T) *vec_ VEC_ASSERT_DECL) \
827 { \
828 vec_assert (vec_->num, "pop"); \
829 --vec_->num; \
830 } \
831 \
832 static inline void VEC_OP (T,truncate) \
833 (VEC(T) *vec_, unsigned size_ VEC_ASSERT_DECL) \
834 { \
835 vec_assert (vec_ ? vec_->num >= size_ : !size_, "truncate"); \
836 if (vec_) \
837 vec_->num = size_; \
838 } \
839 \
840 static inline T *VEC_OP (T,replace) \
841 (VEC(T) *vec_, unsigned ix_, const T *obj_ VEC_ASSERT_DECL) \
842 { \
843 T *slot_; \
844 \
845 vec_assert (ix_ < vec_->num, "replace"); \
846 slot_ = &vec_->vec[ix_]; \
847 if (obj_) \
848 *slot_ = *obj_; \
849 \
850 return slot_; \
851 } \
852 \
853 static inline T *VEC_OP (T,quick_insert) \
854 (VEC(T) *vec_, unsigned ix_, const T *obj_ VEC_ASSERT_DECL) \
855 { \
856 T *slot_; \
857 \
858 vec_assert (vec_->num < vec_->alloc && ix_ <= vec_->num, "quick_insert"); \
859 slot_ = &vec_->vec[ix_]; \
860 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
861 if (obj_) \
862 *slot_ = *obj_; \
863 \
864 return slot_; \
865 } \
866 \
867 static inline void VEC_OP (T,ordered_remove) \
868 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
869 { \
870 T *slot_; \
871 \
872 vec_assert (ix_ < vec_->num, "ordered_remove"); \
873 slot_ = &vec_->vec[ix_]; \
874 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
875 } \
876 \
877 static inline void VEC_OP (T,unordered_remove) \
878 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
879 { \
880 vec_assert (ix_ < vec_->num, "unordered_remove"); \
881 vec_->vec[ix_] = vec_->vec[--vec_->num]; \
882 } \
883 \
884 static inline void VEC_OP (T,block_remove) \
885 (VEC(T) *vec_, unsigned ix_, unsigned len_ VEC_ASSERT_DECL) \
886 { \
887 T *slot_; \
888 \
889 vec_assert (ix_ + len_ <= vec_->num, "block_remove"); \
890 slot_ = &vec_->vec[ix_]; \
891 vec_->num -= len_; \
892 memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
893 } \
894 \
895 static inline T *VEC_OP (T,address) \
896 (VEC(T) *vec_) \
897 { \
898 return vec_ ? vec_->vec : 0; \
899 } \
900 \
901 static inline unsigned VEC_OP (T,lower_bound) \
902 (VEC(T) *vec_, const T *obj_, \
903 int (*lessthan_)(const T *, const T *) VEC_ASSERT_DECL) \
904 { \
905 unsigned int len_ = VEC_OP (T, length) (vec_); \
906 unsigned int half_, middle_; \
907 unsigned int first_ = 0; \
908 while (len_ > 0) \
909 { \
910 T *middle_elem_; \
911 half_ = len_ >> 1; \
912 middle_ = first_; \
913 middle_ += half_; \
914 middle_elem_ = VEC_OP (T,index) (vec_, middle_ VEC_ASSERT_PASS); \
915 if (lessthan_ (middle_elem_, obj_)) \
916 { \
917 first_ = middle_; \
918 ++first_; \
919 len_ = len_ - half_ - 1; \
920 } \
921 else \
922 len_ = half_; \
923 } \
924 return first_; \
925 }
926
927 #define DEF_VEC_ALLOC_FUNC_O(T) \
928 static inline VEC(T) *VEC_OP (T,alloc) \
929 (int alloc_) \
930 { \
931 /* We must request exact size allocation, hence the negation. */ \
932 return (VEC(T) *) vec_o_reserve (NULL, -alloc_, \
933 offsetof (VEC(T),vec), sizeof (T)); \
934 } \
935 \
936 static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_) \
937 { \
938 size_t len_ = vec_ ? vec_->num : 0; \
939 VEC (T) *new_vec_ = NULL; \
940 \
941 if (len_) \
942 { \
943 /* We must request exact size allocation, hence the negation. */ \
944 new_vec_ = (VEC (T) *) \
945 vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T)); \
946 \
947 new_vec_->num = len_; \
948 memcpy (new_vec_->vec, vec_->vec, sizeof (T) * len_); \
949 } \
950 return new_vec_; \
951 } \
952 \
953 static inline void VEC_OP (T,free) \
954 (VEC(T) **vec_) \
955 { \
956 if (*vec_) \
957 vec_free (*vec_); \
958 *vec_ = NULL; \
959 } \
960 \
961 static inline int VEC_OP (T,reserve) \
962 (VEC(T) **vec_, int alloc_ VEC_ASSERT_DECL) \
963 { \
964 int extend = !VEC_OP (T,space) (*vec_, alloc_ < 0 ? -alloc_ : alloc_ \
965 VEC_ASSERT_PASS); \
966 \
967 if (extend) \
968 *vec_ = (VEC(T) *) \
969 vec_o_reserve (*vec_, alloc_, offsetof (VEC(T),vec), sizeof (T)); \
970 \
971 return extend; \
972 } \
973 \
974 static inline void VEC_OP (T,safe_grow) \
975 (VEC(T) **vec_, int size_ VEC_ASSERT_DECL) \
976 { \
977 vec_assert (size_ >= 0 && VEC_OP(T,length) (*vec_) <= (unsigned)size_, \
978 "safe_grow"); \
979 VEC_OP (T,reserve) \
980 (vec_, (int)(*vec_ ? (*vec_)->num : 0) - size_ VEC_ASSERT_PASS); \
981 (*vec_)->num = size_; \
982 } \
983 \
984 static inline T *VEC_OP (T,safe_push) \
985 (VEC(T) **vec_, const T *obj_ VEC_ASSERT_DECL) \
986 { \
987 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
988 \
989 return VEC_OP (T,quick_push) (*vec_, obj_ VEC_ASSERT_PASS); \
990 } \
991 \
992 static inline T *VEC_OP (T,safe_insert) \
993 (VEC(T) **vec_, unsigned ix_, const T *obj_ VEC_ASSERT_DECL) \
994 { \
995 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
996 \
997 return VEC_OP (T,quick_insert) (*vec_, ix_, obj_ VEC_ASSERT_PASS); \
998 }
999
1000 #endif /* GDB_VEC_H */