2 Copyright (C) 2004-2015 Free Software Foundation, Inc.
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
5 This file is part of GDB.
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 3 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #if !defined (GDB_VEC_H)
23 /* The macros here implement a set of templated vector types and
24 associated interfaces. These templates are implemented with
25 macros, as we're not in C++ land. The interface functions are
26 typesafe and use static inline functions, sometimes backed by
27 out-of-line generic functions.
29 Because of the different behavior of structure objects, scalar
30 objects and of pointers, there are three flavors, one for each of
31 these variants. Both the structure object and pointer variants
32 pass pointers to objects around -- in the former case the pointers
33 are stored into the vector and in the latter case the pointers are
34 dereferenced and the objects copied into the vector. The scalar
35 object variant is suitable for int-like objects, and the vector
36 elements are returned by value.
38 There are both 'index' and 'iterate' accessors. The iterator
39 returns a boolean iteration condition and updates the iteration
40 variable passed by reference. Because the iterator will be
41 inlined, the address-of can be optimized away.
43 The vectors are implemented using the trailing array idiom, thus
44 they are not resizeable without changing the address of the vector
45 object itself. This means you cannot have variables or fields of
46 vector type -- always use a pointer to a vector. The one exception
47 is the final field of a structure, which could be a vector type.
48 You will have to use the embedded_size & embedded_init calls to
49 create such objects, and they will probably not be resizeable (so
50 don't use the 'safe' allocation variants). The trailing array
51 idiom is used (rather than a pointer to an array of data), because,
52 if we allow NULL to also represent an empty vector, empty vectors
53 occupy minimal space in the structure containing them.
55 Each operation that increases the number of active elements is
56 available in 'quick' and 'safe' variants. The former presumes that
57 there is sufficient allocated space for the operation to succeed
58 (it dies if there is not). The latter will reallocate the
59 vector, if needed. Reallocation causes an exponential increase in
60 vector size. If you know you will be adding N elements, it would
61 be more efficient to use the reserve operation before adding the
62 elements with the 'quick' operation. This will ensure there are at
63 least as many elements as you ask for, it will exponentially
64 increase if there are too few spare slots. If you want reserve a
65 specific number of slots, but do not want the exponential increase
66 (for instance, you know this is the last allocation), use a
67 negative number for reservation. You can also create a vector of a
68 specific size from the get go.
70 You should prefer the push and pop operations, as they append and
71 remove from the end of the vector. If you need to remove several
72 items in one go, use the truncate operation. The insert and remove
73 operations allow you to change elements in the middle of the
74 vector. There are two remove operations, one which preserves the
75 element ordering 'ordered_remove', and one which does not
76 'unordered_remove'. The latter function copies the end element
77 into the removed slot, rather than invoke a memmove operation. The
78 'lower_bound' function will determine where to place an item in the
79 array using insert that will maintain sorted order.
81 If you need to directly manipulate a vector, then the 'address'
82 accessor will return the address of the start of the vector. Also
83 the 'space' predicate will tell you whether there is spare capacity
84 in the vector. You will not normally need to use these two functions.
86 Vector types are defined using a DEF_VEC_{O,P,I}(TYPEDEF) macro.
87 Variables of vector type are declared using a VEC(TYPEDEF) macro.
88 The characters O, P and I indicate whether TYPEDEF is a pointer
89 (P), object (O) or integral (I) type. Be careful to pick the
90 correct one, as you'll get an awkward and inefficient API if you
91 use the wrong one. There is a check, which results in a
92 compile-time warning, for the P and I versions, but there is no
93 check for the O versions, as that is not possible in plain C.
95 An example of their use would be,
97 DEF_VEC_P(tree); // non-managed tree vector.
100 VEC(tree) *v; // A (pointer to) a vector of tree pointers.
105 if (VEC_length(tree, s->v)) { we have some contents }
106 VEC_safe_push(tree, s->v, decl); // append some decl onto the end
107 for (ix = 0; VEC_iterate(tree, s->v, ix, elt); ix++)
108 { do something with elt }
112 /* Macros to invoke API calls. A single macro works for both pointer
113 and object vectors, but the argument and return types might well be
114 different. In each macro, T is the typedef of the vector elements.
115 Some of these macros pass the vector, V, by reference (by taking
116 its address), this is noted in the descriptions. */
119 unsigned VEC_T_length(const VEC(T) *v);
121 Return the number of active elements in V. V can be NULL, in which
122 case zero is returned. */
124 #define VEC_length(T,V) (VEC_OP(T,length)(V))
127 /* Check if vector is empty
128 int VEC_T_empty(const VEC(T) *v);
130 Return nonzero if V is an empty vector (or V is NULL), zero otherwise. */
132 #define VEC_empty(T,V) (VEC_length (T,V) == 0)
135 /* Get the final element of the vector.
136 T VEC_T_last(VEC(T) *v); // Integer
137 T VEC_T_last(VEC(T) *v); // Pointer
138 T *VEC_T_last(VEC(T) *v); // Object
140 Return the final element. V must not be empty. */
142 #define VEC_last(T,V) (VEC_OP(T,last)(V VEC_ASSERT_INFO))
145 T VEC_T_index(VEC(T) *v, unsigned ix); // Integer
146 T VEC_T_index(VEC(T) *v, unsigned ix); // Pointer
147 T *VEC_T_index(VEC(T) *v, unsigned ix); // Object
149 Return the IX'th element. If IX must be in the domain of V. */
151 #define VEC_index(T,V,I) (VEC_OP(T,index)(V,I VEC_ASSERT_INFO))
153 /* Iterate over vector
154 int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Integer
155 int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Pointer
156 int VEC_T_iterate(VEC(T) *v, unsigned ix, T *&ptr); // Object
158 Return iteration condition and update PTR to point to the IX'th
159 element. At the end of iteration, sets PTR to NULL. Use this to
160 iterate over the elements of a vector as follows,
162 for (ix = 0; VEC_iterate(T,v,ix,ptr); ix++)
165 #define VEC_iterate(T,V,I,P) (VEC_OP(T,iterate)(V,I,&(P)))
167 /* Allocate new vector.
168 VEC(T,A) *VEC_T_alloc(int reserve);
170 Allocate a new vector with space for RESERVE objects. If RESERVE
171 is zero, NO vector is created. */
173 #define VEC_alloc(T,N) (VEC_OP(T,alloc)(N))
176 void VEC_T_free(VEC(T,A) *&);
178 Free a vector and set it to NULL. */
180 #define VEC_free(T,V) (VEC_OP(T,free)(&V))
182 /* A cleanup function for a vector.
183 void VEC_T_cleanup(void *);
185 Clean up a vector. */
187 #define VEC_cleanup(T) (VEC_OP(T,cleanup))
189 /* Use these to determine the required size and initialization of a
190 vector embedded within another structure (as the final member).
192 size_t VEC_T_embedded_size(int reserve);
193 void VEC_T_embedded_init(VEC(T) *v, int reserve);
195 These allow the caller to perform the memory allocation. */
197 #define VEC_embedded_size(T,N) (VEC_OP(T,embedded_size)(N))
198 #define VEC_embedded_init(T,O,N) (VEC_OP(T,embedded_init)(VEC_BASE(O),N))
201 VEC(T,A) *VEC_T_copy(VEC(T) *);
203 Copy the live elements of a vector into a new vector. The new and
204 old vectors need not be allocated by the same mechanism. */
206 #define VEC_copy(T,V) (VEC_OP(T,copy)(V))
208 /* Merge two vectors.
209 VEC(T,A) *VEC_T_merge(VEC(T) *, VEC(T) *);
211 Copy the live elements of both vectors into a new vector. The new
212 and old vectors need not be allocated by the same mechanism. */
213 #define VEC_merge(T,V1,V2) (VEC_OP(T,merge)(V1, V2))
215 /* Determine if a vector has additional capacity.
217 int VEC_T_space (VEC(T) *v,int reserve)
219 If V has space for RESERVE additional entries, return nonzero. You
220 usually only need to use this if you are doing your own vector
221 reallocation, for instance on an embedded vector. This returns
222 nonzero in exactly the same circumstances that VEC_T_reserve
225 #define VEC_space(T,V,R) (VEC_OP(T,space)(V,R VEC_ASSERT_INFO))
228 int VEC_T_reserve(VEC(T,A) *&v, int reserve);
230 Ensure that V has at least abs(RESERVE) slots available. The
231 signedness of RESERVE determines the reallocation behavior. A
232 negative value will not create additional headroom beyond that
233 requested. A positive value will create additional headroom. Note
234 this can cause V to be reallocated. Returns nonzero iff
235 reallocation actually occurred. */
237 #define VEC_reserve(T,V,R) (VEC_OP(T,reserve)(&(V),R VEC_ASSERT_INFO))
239 /* Push object with no reallocation
240 T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer
241 T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
242 T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
244 Push a new element onto the end, returns a pointer to the slot
245 filled in. For object vectors, the new value can be NULL, in which
246 case NO initialization is performed. There must
247 be sufficient space in the vector. */
249 #define VEC_quick_push(T,V,O) (VEC_OP(T,quick_push)(V,O VEC_ASSERT_INFO))
251 /* Push object with reallocation
252 T *VEC_T_safe_push (VEC(T,A) *&v, T obj); // Integer
253 T *VEC_T_safe_push (VEC(T,A) *&v, T obj); // Pointer
254 T *VEC_T_safe_push (VEC(T,A) *&v, T *obj); // Object
256 Push a new element onto the end, returns a pointer to the slot
257 filled in. For object vectors, the new value can be NULL, in which
258 case NO initialization is performed. Reallocates V, if needed. */
260 #define VEC_safe_push(T,V,O) (VEC_OP(T,safe_push)(&(V),O VEC_ASSERT_INFO))
262 /* Pop element off end
263 T VEC_T_pop (VEC(T) *v); // Integer
264 T VEC_T_pop (VEC(T) *v); // Pointer
265 void VEC_T_pop (VEC(T) *v); // Object
267 Pop the last element off the end. Returns the element popped, for
270 #define VEC_pop(T,V) (VEC_OP(T,pop)(V VEC_ASSERT_INFO))
272 /* Truncate to specific length
273 void VEC_T_truncate (VEC(T) *v, unsigned len);
275 Set the length as specified. The new length must be less than or
276 equal to the current length. This is an O(1) operation. */
278 #define VEC_truncate(T,V,I) \
279 (VEC_OP(T,truncate)(V,I VEC_ASSERT_INFO))
281 /* Grow to a specific length.
282 void VEC_T_safe_grow (VEC(T,A) *&v, int len);
284 Grow the vector to a specific length. The LEN must be as
285 long or longer than the current length. The new elements are
288 #define VEC_safe_grow(T,V,I) \
289 (VEC_OP(T,safe_grow)(&(V),I VEC_ASSERT_INFO))
292 T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Integer
293 T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Pointer
294 T *VEC_T_replace (VEC(T) *v, unsigned ix, T *val); // Object
296 Replace the IXth element of V with a new value, VAL. For pointer
297 vectors returns the original value. For object vectors returns a
298 pointer to the new value. For object vectors the new value can be
299 NULL, in which case no overwriting of the slot is actually
302 #define VEC_replace(T,V,I,O) (VEC_OP(T,replace)(V,I,O VEC_ASSERT_INFO))
304 /* Insert object with no reallocation
305 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Integer
306 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer
307 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object
309 Insert an element, VAL, at the IXth position of V. Return a pointer
310 to the slot created. For vectors of object, the new value can be
311 NULL, in which case no initialization of the inserted slot takes
312 place. There must be sufficient space. */
314 #define VEC_quick_insert(T,V,I,O) \
315 (VEC_OP(T,quick_insert)(V,I,O VEC_ASSERT_INFO))
317 /* Insert object with reallocation
318 T *VEC_T_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Integer
319 T *VEC_T_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Pointer
320 T *VEC_T_safe_insert (VEC(T,A) *&v, unsigned ix, T *val); // Object
322 Insert an element, VAL, at the IXth position of V. Return a pointer
323 to the slot created. For vectors of object, the new value can be
324 NULL, in which case no initialization of the inserted slot takes
325 place. Reallocate V, if necessary. */
327 #define VEC_safe_insert(T,V,I,O) \
328 (VEC_OP(T,safe_insert)(&(V),I,O VEC_ASSERT_INFO))
330 /* Remove element retaining order
331 T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Integer
332 T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer
333 void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Object
335 Remove an element from the IXth position of V. Ordering of
336 remaining elements is preserved. For pointer vectors returns the
337 removed object. This is an O(N) operation due to a memmove. */
339 #define VEC_ordered_remove(T,V,I) \
340 (VEC_OP(T,ordered_remove)(V,I VEC_ASSERT_INFO))
342 /* Remove element destroying order
343 T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Integer
344 T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer
345 void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Object
347 Remove an element from the IXth position of V. Ordering of
348 remaining elements is destroyed. For pointer vectors returns the
349 removed object. This is an O(1) operation. */
351 #define VEC_unordered_remove(T,V,I) \
352 (VEC_OP(T,unordered_remove)(V,I VEC_ASSERT_INFO))
354 /* Remove a block of elements
355 void VEC_T_block_remove (VEC(T) *v, unsigned ix, unsigned len);
357 Remove LEN elements starting at the IXth. Ordering is retained.
358 This is an O(N) operation due to memmove. */
360 #define VEC_block_remove(T,V,I,L) \
361 (VEC_OP(T,block_remove)(V,I,L VEC_ASSERT_INFO))
363 /* Get the address of the array of elements
364 T *VEC_T_address (VEC(T) v)
366 If you need to directly manipulate the array (for instance, you
367 want to feed it to qsort), use this accessor. */
369 #define VEC_address(T,V) (VEC_OP(T,address)(V))
371 /* Find the first index in the vector not less than the object.
372 unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
373 int (*lessthan) (const T, const T)); // Integer
374 unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
375 int (*lessthan) (const T, const T)); // Pointer
376 unsigned VEC_T_lower_bound (VEC(T) *v, const T *val,
377 int (*lessthan) (const T*, const T*)); // Object
379 Find the first position in which VAL could be inserted without
380 changing the ordering of V. LESSTHAN is a function that returns
381 true if the first argument is strictly less than the second. */
383 #define VEC_lower_bound(T,V,O,LT) \
384 (VEC_OP(T,lower_bound)(V,O,LT VEC_ASSERT_INFO))
386 /* Reallocate an array of elements with prefix. */
387 extern void *vec_p_reserve (void *, int);
388 extern void *vec_o_reserve (void *, int, size_t, size_t);
389 #define vec_free_(V) xfree (V)
391 #define VEC_ASSERT_INFO ,__FILE__,__LINE__
392 #define VEC_ASSERT_DECL ,const char *file_,unsigned line_
393 #define VEC_ASSERT_PASS ,file_,line_
394 #define vec_assert(expr, op) \
395 ((void)((expr) ? 0 : (gdb_assert_fail (op, file_, line_, \
398 #define VEC(T) VEC_##T
399 #define VEC_OP(T,OP) VEC_##T##_##OP
402 typedef struct VEC(T) \
409 /* Vector of integer-like object. */
410 #define DEF_VEC_I(T) \
411 static inline void VEC_OP (T,must_be_integral_type) (void) \
418 DEF_VEC_ALLOC_FUNC_I(T) \
419 struct vec_swallow_trailing_semi
421 /* Vector of pointer to object. */
422 #define DEF_VEC_P(T) \
423 static inline void VEC_OP (T,must_be_pointer_type) (void) \
425 (void)((T)1 == (void *)1); \
430 DEF_VEC_ALLOC_FUNC_P(T) \
431 struct vec_swallow_trailing_semi
433 /* Vector of object. */
434 #define DEF_VEC_O(T) \
437 DEF_VEC_ALLOC_FUNC_O(T) \
438 struct vec_swallow_trailing_semi
440 #define DEF_VEC_ALLOC_FUNC_I(T) \
441 static inline VEC(T) *VEC_OP (T,alloc) \
444 /* We must request exact size allocation, hence the negation. */ \
445 return (VEC(T) *) vec_o_reserve (NULL, -alloc_, \
446 offsetof (VEC(T),vec), sizeof (T)); \
449 static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_) \
451 size_t len_ = vec_ ? vec_->num : 0; \
452 VEC (T) *new_vec_ = NULL; \
456 /* We must request exact size allocation, hence the negation. */ \
457 new_vec_ = (VEC (T) *) \
458 vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T)); \
460 new_vec_->num = len_; \
461 memcpy (new_vec_->vec, vec_->vec, sizeof (T) * len_); \
466 static inline VEC(T) *VEC_OP (T,merge) (VEC(T) *vec1_, VEC(T) *vec2_) \
468 if (vec1_ && vec2_) \
470 size_t len_ = vec1_->num + vec2_->num; \
471 VEC (T) *new_vec_ = NULL; \
473 /* We must request exact size allocation, hence the negation. */ \
474 new_vec_ = (VEC (T) *) \
475 vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T)); \
477 new_vec_->num = len_; \
478 memcpy (new_vec_->vec, vec1_->vec, sizeof (T) * vec1_->num); \
479 memcpy (new_vec_->vec + vec1_->num, vec2_->vec, \
480 sizeof (T) * vec2_->num); \
485 return VEC_copy (T, vec1_ ? vec1_ : vec2_); \
488 static inline void VEC_OP (T,free) \
496 static inline void VEC_OP (T,cleanup) \
499 VEC(T) **vec_ = arg_; \
505 static inline int VEC_OP (T,reserve) \
506 (VEC(T) **vec_, int alloc_ VEC_ASSERT_DECL) \
508 int extend = !VEC_OP (T,space) \
509 (*vec_, alloc_ < 0 ? -alloc_ : alloc_ VEC_ASSERT_PASS); \
512 *vec_ = (VEC(T) *) vec_o_reserve (*vec_, alloc_, \
513 offsetof (VEC(T),vec), sizeof (T)); \
518 static inline void VEC_OP (T,safe_grow) \
519 (VEC(T) **vec_, int size_ VEC_ASSERT_DECL) \
521 vec_assert (size_ >= 0 && VEC_OP(T,length) (*vec_) <= (unsigned)size_, \
523 VEC_OP (T,reserve) (vec_, (int)(*vec_ ? (*vec_)->num : 0) - size_ \
525 (*vec_)->num = size_; \
528 static inline T *VEC_OP (T,safe_push) \
529 (VEC(T) **vec_, const T obj_ VEC_ASSERT_DECL) \
531 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
533 return VEC_OP (T,quick_push) (*vec_, obj_ VEC_ASSERT_PASS); \
536 static inline T *VEC_OP (T,safe_insert) \
537 (VEC(T) **vec_, unsigned ix_, const T obj_ VEC_ASSERT_DECL) \
539 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
541 return VEC_OP (T,quick_insert) (*vec_, ix_, obj_ VEC_ASSERT_PASS); \
544 #define DEF_VEC_FUNC_P(T) \
545 static inline unsigned VEC_OP (T,length) (const VEC(T) *vec_) \
547 return vec_ ? vec_->num : 0; \
550 static inline T VEC_OP (T,last) \
551 (const VEC(T) *vec_ VEC_ASSERT_DECL) \
553 vec_assert (vec_ && vec_->num, "last"); \
555 return vec_->vec[vec_->num - 1]; \
558 static inline T VEC_OP (T,index) \
559 (const VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
561 vec_assert (vec_ && ix_ < vec_->num, "index"); \
563 return vec_->vec[ix_]; \
566 static inline int VEC_OP (T,iterate) \
567 (const VEC(T) *vec_, unsigned ix_, T *ptr) \
569 if (vec_ && ix_ < vec_->num) \
571 *ptr = vec_->vec[ix_]; \
581 static inline size_t VEC_OP (T,embedded_size) \
584 return offsetof (VEC(T),vec) + alloc_ * sizeof(T); \
587 static inline void VEC_OP (T,embedded_init) \
588 (VEC(T) *vec_, int alloc_) \
591 vec_->alloc = alloc_; \
594 static inline int VEC_OP (T,space) \
595 (VEC(T) *vec_, int alloc_ VEC_ASSERT_DECL) \
597 vec_assert (alloc_ >= 0, "space"); \
598 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
601 static inline T *VEC_OP (T,quick_push) \
602 (VEC(T) *vec_, T obj_ VEC_ASSERT_DECL) \
606 vec_assert (vec_->num < vec_->alloc, "quick_push"); \
607 slot_ = &vec_->vec[vec_->num++]; \
613 static inline T VEC_OP (T,pop) (VEC(T) *vec_ VEC_ASSERT_DECL) \
617 vec_assert (vec_->num, "pop"); \
618 obj_ = vec_->vec[--vec_->num]; \
623 static inline void VEC_OP (T,truncate) \
624 (VEC(T) *vec_, unsigned size_ VEC_ASSERT_DECL) \
626 vec_assert (vec_ ? vec_->num >= size_ : !size_, "truncate"); \
631 static inline T VEC_OP (T,replace) \
632 (VEC(T) *vec_, unsigned ix_, T obj_ VEC_ASSERT_DECL) \
636 vec_assert (ix_ < vec_->num, "replace"); \
637 old_obj_ = vec_->vec[ix_]; \
638 vec_->vec[ix_] = obj_; \
643 static inline T *VEC_OP (T,quick_insert) \
644 (VEC(T) *vec_, unsigned ix_, T obj_ VEC_ASSERT_DECL) \
648 vec_assert (vec_->num < vec_->alloc && ix_ <= vec_->num, "quick_insert"); \
649 slot_ = &vec_->vec[ix_]; \
650 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
656 static inline T VEC_OP (T,ordered_remove) \
657 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
662 vec_assert (ix_ < vec_->num, "ordered_remove"); \
663 slot_ = &vec_->vec[ix_]; \
665 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
670 static inline T VEC_OP (T,unordered_remove) \
671 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
676 vec_assert (ix_ < vec_->num, "unordered_remove"); \
677 slot_ = &vec_->vec[ix_]; \
679 *slot_ = vec_->vec[--vec_->num]; \
684 static inline void VEC_OP (T,block_remove) \
685 (VEC(T) *vec_, unsigned ix_, unsigned len_ VEC_ASSERT_DECL) \
689 vec_assert (ix_ + len_ <= vec_->num, "block_remove"); \
690 slot_ = &vec_->vec[ix_]; \
692 memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
695 static inline T *VEC_OP (T,address) \
698 return vec_ ? vec_->vec : 0; \
701 static inline unsigned VEC_OP (T,lower_bound) \
702 (VEC(T) *vec_, const T obj_, \
703 int (*lessthan_)(const T, const T) VEC_ASSERT_DECL) \
705 unsigned int len_ = VEC_OP (T, length) (vec_); \
706 unsigned int half_, middle_; \
707 unsigned int first_ = 0; \
714 middle_elem_ = VEC_OP (T,index) (vec_, middle_ VEC_ASSERT_PASS); \
715 if (lessthan_ (middle_elem_, obj_)) \
719 len_ = len_ - half_ - 1; \
727 #define DEF_VEC_ALLOC_FUNC_P(T) \
728 static inline VEC(T) *VEC_OP (T,alloc) \
731 /* We must request exact size allocation, hence the negation. */ \
732 return (VEC(T) *) vec_p_reserve (NULL, -alloc_); \
735 static inline void VEC_OP (T,free) \
743 static inline void VEC_OP (T,cleanup) \
746 VEC(T) **vec_ = arg_; \
752 static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_) \
754 size_t len_ = vec_ ? vec_->num : 0; \
755 VEC (T) *new_vec_ = NULL; \
759 /* We must request exact size allocation, hence the negation. */ \
760 new_vec_ = (VEC (T) *)(vec_p_reserve (NULL, -len_)); \
762 new_vec_->num = len_; \
763 memcpy (new_vec_->vec, vec_->vec, sizeof (T) * len_); \
768 static inline VEC(T) *VEC_OP (T,merge) (VEC(T) *vec1_, VEC(T) *vec2_) \
770 if (vec1_ && vec2_) \
772 size_t len_ = vec1_->num + vec2_->num; \
773 VEC (T) *new_vec_ = NULL; \
775 /* We must request exact size allocation, hence the negation. */ \
776 new_vec_ = (VEC (T) *)(vec_p_reserve (NULL, -len_)); \
778 new_vec_->num = len_; \
779 memcpy (new_vec_->vec, vec1_->vec, sizeof (T) * vec1_->num); \
780 memcpy (new_vec_->vec + vec1_->num, vec2_->vec, \
781 sizeof (T) * vec2_->num); \
786 return VEC_copy (T, vec1_ ? vec1_ : vec2_); \
789 static inline int VEC_OP (T,reserve) \
790 (VEC(T) **vec_, int alloc_ VEC_ASSERT_DECL) \
792 int extend = !VEC_OP (T,space) \
793 (*vec_, alloc_ < 0 ? -alloc_ : alloc_ VEC_ASSERT_PASS); \
796 *vec_ = (VEC(T) *) vec_p_reserve (*vec_, alloc_); \
801 static inline void VEC_OP (T,safe_grow) \
802 (VEC(T) **vec_, int size_ VEC_ASSERT_DECL) \
804 vec_assert (size_ >= 0 && VEC_OP(T,length) (*vec_) <= (unsigned)size_, \
807 (vec_, (int)(*vec_ ? (*vec_)->num : 0) - size_ VEC_ASSERT_PASS); \
808 (*vec_)->num = size_; \
811 static inline T *VEC_OP (T,safe_push) \
812 (VEC(T) **vec_, T obj_ VEC_ASSERT_DECL) \
814 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
816 return VEC_OP (T,quick_push) (*vec_, obj_ VEC_ASSERT_PASS); \
819 static inline T *VEC_OP (T,safe_insert) \
820 (VEC(T) **vec_, unsigned ix_, T obj_ VEC_ASSERT_DECL) \
822 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
824 return VEC_OP (T,quick_insert) (*vec_, ix_, obj_ VEC_ASSERT_PASS); \
827 #define DEF_VEC_FUNC_O(T) \
828 static inline unsigned VEC_OP (T,length) (const VEC(T) *vec_) \
830 return vec_ ? vec_->num : 0; \
833 static inline T *VEC_OP (T,last) (VEC(T) *vec_ VEC_ASSERT_DECL) \
835 vec_assert (vec_ && vec_->num, "last"); \
837 return &vec_->vec[vec_->num - 1]; \
840 static inline T *VEC_OP (T,index) \
841 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
843 vec_assert (vec_ && ix_ < vec_->num, "index"); \
845 return &vec_->vec[ix_]; \
848 static inline int VEC_OP (T,iterate) \
849 (VEC(T) *vec_, unsigned ix_, T **ptr) \
851 if (vec_ && ix_ < vec_->num) \
853 *ptr = &vec_->vec[ix_]; \
863 static inline size_t VEC_OP (T,embedded_size) \
866 return offsetof (VEC(T),vec) + alloc_ * sizeof(T); \
869 static inline void VEC_OP (T,embedded_init) \
870 (VEC(T) *vec_, int alloc_) \
873 vec_->alloc = alloc_; \
876 static inline int VEC_OP (T,space) \
877 (VEC(T) *vec_, int alloc_ VEC_ASSERT_DECL) \
879 vec_assert (alloc_ >= 0, "space"); \
880 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
883 static inline T *VEC_OP (T,quick_push) \
884 (VEC(T) *vec_, const T *obj_ VEC_ASSERT_DECL) \
888 vec_assert (vec_->num < vec_->alloc, "quick_push"); \
889 slot_ = &vec_->vec[vec_->num++]; \
896 static inline void VEC_OP (T,pop) (VEC(T) *vec_ VEC_ASSERT_DECL) \
898 vec_assert (vec_->num, "pop"); \
902 static inline void VEC_OP (T,truncate) \
903 (VEC(T) *vec_, unsigned size_ VEC_ASSERT_DECL) \
905 vec_assert (vec_ ? vec_->num >= size_ : !size_, "truncate"); \
910 static inline T *VEC_OP (T,replace) \
911 (VEC(T) *vec_, unsigned ix_, const T *obj_ VEC_ASSERT_DECL) \
915 vec_assert (ix_ < vec_->num, "replace"); \
916 slot_ = &vec_->vec[ix_]; \
923 static inline T *VEC_OP (T,quick_insert) \
924 (VEC(T) *vec_, unsigned ix_, const T *obj_ VEC_ASSERT_DECL) \
928 vec_assert (vec_->num < vec_->alloc && ix_ <= vec_->num, "quick_insert"); \
929 slot_ = &vec_->vec[ix_]; \
930 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
937 static inline void VEC_OP (T,ordered_remove) \
938 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
942 vec_assert (ix_ < vec_->num, "ordered_remove"); \
943 slot_ = &vec_->vec[ix_]; \
944 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
947 static inline void VEC_OP (T,unordered_remove) \
948 (VEC(T) *vec_, unsigned ix_ VEC_ASSERT_DECL) \
950 vec_assert (ix_ < vec_->num, "unordered_remove"); \
951 vec_->vec[ix_] = vec_->vec[--vec_->num]; \
954 static inline void VEC_OP (T,block_remove) \
955 (VEC(T) *vec_, unsigned ix_, unsigned len_ VEC_ASSERT_DECL) \
959 vec_assert (ix_ + len_ <= vec_->num, "block_remove"); \
960 slot_ = &vec_->vec[ix_]; \
962 memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
965 static inline T *VEC_OP (T,address) \
968 return vec_ ? vec_->vec : 0; \
971 static inline unsigned VEC_OP (T,lower_bound) \
972 (VEC(T) *vec_, const T *obj_, \
973 int (*lessthan_)(const T *, const T *) VEC_ASSERT_DECL) \
975 unsigned int len_ = VEC_OP (T, length) (vec_); \
976 unsigned int half_, middle_; \
977 unsigned int first_ = 0; \
984 middle_elem_ = VEC_OP (T,index) (vec_, middle_ VEC_ASSERT_PASS); \
985 if (lessthan_ (middle_elem_, obj_)) \
989 len_ = len_ - half_ - 1; \
997 #define DEF_VEC_ALLOC_FUNC_O(T) \
998 static inline VEC(T) *VEC_OP (T,alloc) \
1001 /* We must request exact size allocation, hence the negation. */ \
1002 return (VEC(T) *) vec_o_reserve (NULL, -alloc_, \
1003 offsetof (VEC(T),vec), sizeof (T)); \
1006 static inline VEC(T) *VEC_OP (T,copy) (VEC(T) *vec_) \
1008 size_t len_ = vec_ ? vec_->num : 0; \
1009 VEC (T) *new_vec_ = NULL; \
1013 /* We must request exact size allocation, hence the negation. */ \
1014 new_vec_ = (VEC (T) *) \
1015 vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T)); \
1017 new_vec_->num = len_; \
1018 memcpy (new_vec_->vec, vec_->vec, sizeof (T) * len_); \
1023 static inline VEC(T) *VEC_OP (T,merge) (VEC(T) *vec1_, VEC(T) *vec2_) \
1025 if (vec1_ && vec2_) \
1027 size_t len_ = vec1_->num + vec2_->num; \
1028 VEC (T) *new_vec_ = NULL; \
1030 /* We must request exact size allocation, hence the negation. */ \
1031 new_vec_ = (VEC (T) *) \
1032 vec_o_reserve (NULL, -len_, offsetof (VEC(T),vec), sizeof (T)); \
1034 new_vec_->num = len_; \
1035 memcpy (new_vec_->vec, vec1_->vec, sizeof (T) * vec1_->num); \
1036 memcpy (new_vec_->vec + vec1_->num, vec2_->vec, \
1037 sizeof (T) * vec2_->num); \
1042 return VEC_copy (T, vec1_ ? vec1_ : vec2_); \
1045 static inline void VEC_OP (T,free) \
1049 vec_free_ (*vec_); \
1053 static inline void VEC_OP (T,cleanup) \
1056 VEC(T) **vec_ = arg_; \
1058 vec_free_ (*vec_); \
1062 static inline int VEC_OP (T,reserve) \
1063 (VEC(T) **vec_, int alloc_ VEC_ASSERT_DECL) \
1065 int extend = !VEC_OP (T,space) (*vec_, alloc_ < 0 ? -alloc_ : alloc_ \
1069 *vec_ = (VEC(T) *) \
1070 vec_o_reserve (*vec_, alloc_, offsetof (VEC(T),vec), sizeof (T)); \
1075 static inline void VEC_OP (T,safe_grow) \
1076 (VEC(T) **vec_, int size_ VEC_ASSERT_DECL) \
1078 vec_assert (size_ >= 0 && VEC_OP(T,length) (*vec_) <= (unsigned)size_, \
1080 VEC_OP (T,reserve) \
1081 (vec_, (int)(*vec_ ? (*vec_)->num : 0) - size_ VEC_ASSERT_PASS); \
1082 (*vec_)->num = size_; \
1085 static inline T *VEC_OP (T,safe_push) \
1086 (VEC(T) **vec_, const T *obj_ VEC_ASSERT_DECL) \
1088 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
1090 return VEC_OP (T,quick_push) (*vec_, obj_ VEC_ASSERT_PASS); \
1093 static inline T *VEC_OP (T,safe_insert) \
1094 (VEC(T) **vec_, unsigned ix_, const T *obj_ VEC_ASSERT_DECL) \
1096 VEC_OP (T,reserve) (vec_, 1 VEC_ASSERT_PASS); \
1098 return VEC_OP (T,quick_insert) (*vec_, ix_, obj_ VEC_ASSERT_PASS); \
1101 #endif /* GDB_VEC_H */
This page took 0.051912 seconds and 4 git commands to generate.