1*e4b17023SJohn Marino /* Vector API for GNU compiler. 2*e4b17023SJohn Marino Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 3*e4b17023SJohn Marino Free Software Foundation, Inc. 4*e4b17023SJohn Marino Contributed by Nathan Sidwell <nathan@codesourcery.com> 5*e4b17023SJohn Marino 6*e4b17023SJohn Marino This file is part of GCC. 7*e4b17023SJohn Marino 8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under 9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free 10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later 11*e4b17023SJohn Marino version. 12*e4b17023SJohn Marino 13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or 15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16*e4b17023SJohn Marino for more details. 17*e4b17023SJohn Marino 18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 21*e4b17023SJohn Marino 22*e4b17023SJohn Marino #ifndef GCC_VEC_H 23*e4b17023SJohn Marino #define GCC_VEC_H 24*e4b17023SJohn Marino 25*e4b17023SJohn Marino #include "statistics.h" /* For MEM_STAT_DECL. */ 26*e4b17023SJohn Marino 27*e4b17023SJohn Marino /* The macros here implement a set of templated vector types and 28*e4b17023SJohn Marino associated interfaces. These templates are implemented with 29*e4b17023SJohn Marino macros, as we're not in C++ land. The interface functions are 30*e4b17023SJohn Marino typesafe and use static inline functions, sometimes backed by 31*e4b17023SJohn Marino out-of-line generic functions. The vectors are designed to 32*e4b17023SJohn Marino interoperate with the GTY machinery. 33*e4b17023SJohn Marino 34*e4b17023SJohn Marino Because of the different behavior of structure objects, scalar 35*e4b17023SJohn Marino objects and of pointers, there are three flavors, one for each of 36*e4b17023SJohn Marino these variants. Both the structure object and pointer variants 37*e4b17023SJohn Marino pass pointers to objects around -- in the former case the pointers 38*e4b17023SJohn Marino are stored into the vector and in the latter case the pointers are 39*e4b17023SJohn Marino dereferenced and the objects copied into the vector. The scalar 40*e4b17023SJohn Marino object variant is suitable for int-like objects, and the vector 41*e4b17023SJohn Marino elements are returned by value. 42*e4b17023SJohn Marino 43*e4b17023SJohn Marino There are both 'index' and 'iterate' accessors. The iterator 44*e4b17023SJohn Marino returns a boolean iteration condition and updates the iteration 45*e4b17023SJohn Marino variable passed by reference. Because the iterator will be 46*e4b17023SJohn Marino inlined, the address-of can be optimized away. 47*e4b17023SJohn Marino 48*e4b17023SJohn Marino The vectors are implemented using the trailing array idiom, thus 49*e4b17023SJohn Marino they are not resizeable without changing the address of the vector 50*e4b17023SJohn Marino object itself. This means you cannot have variables or fields of 51*e4b17023SJohn Marino vector type -- always use a pointer to a vector. The one exception 52*e4b17023SJohn Marino is the final field of a structure, which could be a vector type. 53*e4b17023SJohn Marino You will have to use the embedded_size & embedded_init calls to 54*e4b17023SJohn Marino create such objects, and they will probably not be resizeable (so 55*e4b17023SJohn Marino don't use the 'safe' allocation variants). The trailing array 56*e4b17023SJohn Marino idiom is used (rather than a pointer to an array of data), because, 57*e4b17023SJohn Marino if we allow NULL to also represent an empty vector, empty vectors 58*e4b17023SJohn Marino occupy minimal space in the structure containing them. 59*e4b17023SJohn Marino 60*e4b17023SJohn Marino Each operation that increases the number of active elements is 61*e4b17023SJohn Marino available in 'quick' and 'safe' variants. The former presumes that 62*e4b17023SJohn Marino there is sufficient allocated space for the operation to succeed 63*e4b17023SJohn Marino (it dies if there is not). The latter will reallocate the 64*e4b17023SJohn Marino vector, if needed. Reallocation causes an exponential increase in 65*e4b17023SJohn Marino vector size. If you know you will be adding N elements, it would 66*e4b17023SJohn Marino be more efficient to use the reserve operation before adding the 67*e4b17023SJohn Marino elements with the 'quick' operation. This will ensure there are at 68*e4b17023SJohn Marino least as many elements as you ask for, it will exponentially 69*e4b17023SJohn Marino increase if there are too few spare slots. If you want reserve a 70*e4b17023SJohn Marino specific number of slots, but do not want the exponential increase 71*e4b17023SJohn Marino (for instance, you know this is the last allocation), use the 72*e4b17023SJohn Marino reserve_exact operation. You can also create a vector of a 73*e4b17023SJohn Marino specific size from the get go. 74*e4b17023SJohn Marino 75*e4b17023SJohn Marino You should prefer the push and pop operations, as they append and 76*e4b17023SJohn Marino remove from the end of the vector. If you need to remove several 77*e4b17023SJohn Marino items in one go, use the truncate operation. The insert and remove 78*e4b17023SJohn Marino operations allow you to change elements in the middle of the 79*e4b17023SJohn Marino vector. There are two remove operations, one which preserves the 80*e4b17023SJohn Marino element ordering 'ordered_remove', and one which does not 81*e4b17023SJohn Marino 'unordered_remove'. The latter function copies the end element 82*e4b17023SJohn Marino into the removed slot, rather than invoke a memmove operation. The 83*e4b17023SJohn Marino 'lower_bound' function will determine where to place an item in the 84*e4b17023SJohn Marino array using insert that will maintain sorted order. 85*e4b17023SJohn Marino 86*e4b17023SJohn Marino When a vector type is defined, first a non-memory managed version 87*e4b17023SJohn Marino is created. You can then define either or both garbage collected 88*e4b17023SJohn Marino and heap allocated versions. The allocation mechanism is specified 89*e4b17023SJohn Marino when the type is defined, and is therefore part of the type. If 90*e4b17023SJohn Marino you need both gc'd and heap allocated versions, you still must have 91*e4b17023SJohn Marino *exactly* one definition of the common non-memory managed base vector. 92*e4b17023SJohn Marino 93*e4b17023SJohn Marino If you need to directly manipulate a vector, then the 'address' 94*e4b17023SJohn Marino accessor will return the address of the start of the vector. Also 95*e4b17023SJohn Marino the 'space' predicate will tell you whether there is spare capacity 96*e4b17023SJohn Marino in the vector. You will not normally need to use these two functions. 97*e4b17023SJohn Marino 98*e4b17023SJohn Marino Vector types are defined using a DEF_VEC_{O,P,I}(TYPEDEF) macro, to 99*e4b17023SJohn Marino get the non-memory allocation version, and then a 100*e4b17023SJohn Marino DEF_VEC_ALLOC_{O,P,I}(TYPEDEF,ALLOC) macro to get memory managed 101*e4b17023SJohn Marino vectors. Variables of vector type are declared using a 102*e4b17023SJohn Marino VEC(TYPEDEF,ALLOC) macro. The ALLOC argument specifies the 103*e4b17023SJohn Marino allocation strategy, and can be either 'gc' or 'heap' for garbage 104*e4b17023SJohn Marino collected and heap allocated respectively. It can be 'none' to get 105*e4b17023SJohn Marino a vector that must be explicitly allocated (for instance as a 106*e4b17023SJohn Marino trailing array of another structure). The characters O, P and I 107*e4b17023SJohn Marino indicate whether TYPEDEF is a pointer (P), object (O) or integral 108*e4b17023SJohn Marino (I) type. Be careful to pick the correct one, as you'll get an 109*e4b17023SJohn Marino awkward and inefficient API if you use the wrong one. There is a 110*e4b17023SJohn Marino check, which results in a compile-time warning, for the P and I 111*e4b17023SJohn Marino versions, but there is no check for the O versions, as that is not 112*e4b17023SJohn Marino possible in plain C. Due to the way GTY works, you must annotate 113*e4b17023SJohn Marino any structures you wish to insert or reference from a vector with a 114*e4b17023SJohn Marino GTY(()) tag. You need to do this even if you never declare the GC 115*e4b17023SJohn Marino allocated variants. 116*e4b17023SJohn Marino 117*e4b17023SJohn Marino An example of their use would be, 118*e4b17023SJohn Marino 119*e4b17023SJohn Marino DEF_VEC_P(tree); // non-managed tree vector. 120*e4b17023SJohn Marino DEF_VEC_ALLOC_P(tree,gc); // gc'd vector of tree pointers. This must 121*e4b17023SJohn Marino // appear at file scope. 122*e4b17023SJohn Marino 123*e4b17023SJohn Marino struct my_struct { 124*e4b17023SJohn Marino VEC(tree,gc) *v; // A (pointer to) a vector of tree pointers. 125*e4b17023SJohn Marino }; 126*e4b17023SJohn Marino 127*e4b17023SJohn Marino struct my_struct *s; 128*e4b17023SJohn Marino 129*e4b17023SJohn Marino if (VEC_length(tree,s->v)) { we have some contents } 130*e4b17023SJohn Marino VEC_safe_push(tree,gc,s->v,decl); // append some decl onto the end 131*e4b17023SJohn Marino for (ix = 0; VEC_iterate(tree,s->v,ix,elt); ix++) 132*e4b17023SJohn Marino { do something with elt } 133*e4b17023SJohn Marino 134*e4b17023SJohn Marino */ 135*e4b17023SJohn Marino 136*e4b17023SJohn Marino /* Macros to invoke API calls. A single macro works for both pointer 137*e4b17023SJohn Marino and object vectors, but the argument and return types might well be 138*e4b17023SJohn Marino different. In each macro, T is the typedef of the vector elements, 139*e4b17023SJohn Marino and A is the allocation strategy. The allocation strategy is only 140*e4b17023SJohn Marino present when it is required. Some of these macros pass the vector, 141*e4b17023SJohn Marino V, by reference (by taking its address), this is noted in the 142*e4b17023SJohn Marino descriptions. */ 143*e4b17023SJohn Marino 144*e4b17023SJohn Marino /* Length of vector 145*e4b17023SJohn Marino unsigned VEC_T_length(const VEC(T) *v); 146*e4b17023SJohn Marino 147*e4b17023SJohn Marino Return the number of active elements in V. V can be NULL, in which 148*e4b17023SJohn Marino case zero is returned. */ 149*e4b17023SJohn Marino 150*e4b17023SJohn Marino #define VEC_length(T,V) (VEC_OP(T,base,length)(VEC_BASE(V))) 151*e4b17023SJohn Marino 152*e4b17023SJohn Marino 153*e4b17023SJohn Marino /* Check if vector is empty 154*e4b17023SJohn Marino int VEC_T_empty(const VEC(T) *v); 155*e4b17023SJohn Marino 156*e4b17023SJohn Marino Return nonzero if V is an empty vector (or V is NULL), zero otherwise. */ 157*e4b17023SJohn Marino 158*e4b17023SJohn Marino #define VEC_empty(T,V) (VEC_length (T,V) == 0) 159*e4b17023SJohn Marino 160*e4b17023SJohn Marino 161*e4b17023SJohn Marino /* Get the final element of the vector. 162*e4b17023SJohn Marino T VEC_T_last(VEC(T) *v); // Integer 163*e4b17023SJohn Marino T VEC_T_last(VEC(T) *v); // Pointer 164*e4b17023SJohn Marino T *VEC_T_last(VEC(T) *v); // Object 165*e4b17023SJohn Marino 166*e4b17023SJohn Marino Return the final element. V must not be empty. */ 167*e4b17023SJohn Marino 168*e4b17023SJohn Marino #define VEC_last(T,V) (VEC_OP(T,base,last)(VEC_BASE(V) VEC_CHECK_INFO)) 169*e4b17023SJohn Marino 170*e4b17023SJohn Marino /* Index into vector 171*e4b17023SJohn Marino T VEC_T_index(VEC(T) *v, unsigned ix); // Integer 172*e4b17023SJohn Marino T VEC_T_index(VEC(T) *v, unsigned ix); // Pointer 173*e4b17023SJohn Marino T *VEC_T_index(VEC(T) *v, unsigned ix); // Object 174*e4b17023SJohn Marino 175*e4b17023SJohn Marino Return the IX'th element. If IX must be in the domain of V. */ 176*e4b17023SJohn Marino 177*e4b17023SJohn Marino #define VEC_index(T,V,I) (VEC_OP(T,base,index)(VEC_BASE(V),I VEC_CHECK_INFO)) 178*e4b17023SJohn Marino 179*e4b17023SJohn Marino /* Iterate over vector 180*e4b17023SJohn Marino int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Integer 181*e4b17023SJohn Marino int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Pointer 182*e4b17023SJohn Marino int VEC_T_iterate(VEC(T) *v, unsigned ix, T *&ptr); // Object 183*e4b17023SJohn Marino 184*e4b17023SJohn Marino Return iteration condition and update PTR to point to the IX'th 185*e4b17023SJohn Marino element. At the end of iteration, sets PTR to NULL. Use this to 186*e4b17023SJohn Marino iterate over the elements of a vector as follows, 187*e4b17023SJohn Marino 188*e4b17023SJohn Marino for (ix = 0; VEC_iterate(T,v,ix,ptr); ix++) 189*e4b17023SJohn Marino continue; */ 190*e4b17023SJohn Marino 191*e4b17023SJohn Marino #define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P))) 192*e4b17023SJohn Marino 193*e4b17023SJohn Marino /* Convenience macro for forward iteration. */ 194*e4b17023SJohn Marino 195*e4b17023SJohn Marino #define FOR_EACH_VEC_ELT(T, V, I, P) \ 196*e4b17023SJohn Marino for (I = 0; VEC_iterate (T, (V), (I), (P)); ++(I)) 197*e4b17023SJohn Marino 198*e4b17023SJohn Marino /* Likewise, but start from FROM rather than 0. */ 199*e4b17023SJohn Marino 200*e4b17023SJohn Marino #define FOR_EACH_VEC_ELT_FROM(T, V, I, P, FROM) \ 201*e4b17023SJohn Marino for (I = (FROM); VEC_iterate (T, (V), (I), (P)); ++(I)) 202*e4b17023SJohn Marino 203*e4b17023SJohn Marino /* Convenience macro for reverse iteration. */ 204*e4b17023SJohn Marino 205*e4b17023SJohn Marino #define FOR_EACH_VEC_ELT_REVERSE(T,V,I,P) \ 206*e4b17023SJohn Marino for (I = VEC_length (T, (V)) - 1; \ 207*e4b17023SJohn Marino VEC_iterate (T, (V), (I), (P)); \ 208*e4b17023SJohn Marino (I)--) 209*e4b17023SJohn Marino 210*e4b17023SJohn Marino /* Allocate new vector. 211*e4b17023SJohn Marino VEC(T,A) *VEC_T_A_alloc(int reserve); 212*e4b17023SJohn Marino 213*e4b17023SJohn Marino Allocate a new vector with space for RESERVE objects. If RESERVE 214*e4b17023SJohn Marino is zero, NO vector is created. */ 215*e4b17023SJohn Marino 216*e4b17023SJohn Marino #define VEC_alloc(T,A,N) (VEC_OP(T,A,alloc)(N MEM_STAT_INFO)) 217*e4b17023SJohn Marino 218*e4b17023SJohn Marino /* Free a vector. 219*e4b17023SJohn Marino void VEC_T_A_free(VEC(T,A) *&); 220*e4b17023SJohn Marino 221*e4b17023SJohn Marino Free a vector and set it to NULL. */ 222*e4b17023SJohn Marino 223*e4b17023SJohn Marino #define VEC_free(T,A,V) (VEC_OP(T,A,free)(&V)) 224*e4b17023SJohn Marino 225*e4b17023SJohn Marino /* Use these to determine the required size and initialization of a 226*e4b17023SJohn Marino vector embedded within another structure (as the final member). 227*e4b17023SJohn Marino 228*e4b17023SJohn Marino size_t VEC_T_embedded_size(int reserve); 229*e4b17023SJohn Marino void VEC_T_embedded_init(VEC(T) *v, int reserve); 230*e4b17023SJohn Marino 231*e4b17023SJohn Marino These allow the caller to perform the memory allocation. */ 232*e4b17023SJohn Marino 233*e4b17023SJohn Marino #define VEC_embedded_size(T,N) (VEC_OP(T,base,embedded_size)(N)) 234*e4b17023SJohn Marino #define VEC_embedded_init(T,O,N) (VEC_OP(T,base,embedded_init)(VEC_BASE(O),N)) 235*e4b17023SJohn Marino 236*e4b17023SJohn Marino /* Copy a vector. 237*e4b17023SJohn Marino VEC(T,A) *VEC_T_A_copy(VEC(T) *); 238*e4b17023SJohn Marino 239*e4b17023SJohn Marino Copy the live elements of a vector into a new vector. The new and 240*e4b17023SJohn Marino old vectors need not be allocated by the same mechanism. */ 241*e4b17023SJohn Marino 242*e4b17023SJohn Marino #define VEC_copy(T,A,V) (VEC_OP(T,A,copy)(VEC_BASE(V) MEM_STAT_INFO)) 243*e4b17023SJohn Marino 244*e4b17023SJohn Marino /* Determine if a vector has additional capacity. 245*e4b17023SJohn Marino 246*e4b17023SJohn Marino int VEC_T_space (VEC(T) *v,int reserve) 247*e4b17023SJohn Marino 248*e4b17023SJohn Marino If V has space for RESERVE additional entries, return nonzero. You 249*e4b17023SJohn Marino usually only need to use this if you are doing your own vector 250*e4b17023SJohn Marino reallocation, for instance on an embedded vector. This returns 251*e4b17023SJohn Marino nonzero in exactly the same circumstances that VEC_T_reserve 252*e4b17023SJohn Marino will. */ 253*e4b17023SJohn Marino 254*e4b17023SJohn Marino #define VEC_space(T,V,R) \ 255*e4b17023SJohn Marino (VEC_OP(T,base,space)(VEC_BASE(V),R VEC_CHECK_INFO)) 256*e4b17023SJohn Marino 257*e4b17023SJohn Marino /* Reserve space. 258*e4b17023SJohn Marino int VEC_T_A_reserve(VEC(T,A) *&v, int reserve); 259*e4b17023SJohn Marino 260*e4b17023SJohn Marino Ensure that V has at least RESERVE slots available. This will 261*e4b17023SJohn Marino create additional headroom. Note this can cause V to be 262*e4b17023SJohn Marino reallocated. Returns nonzero iff reallocation actually 263*e4b17023SJohn Marino occurred. */ 264*e4b17023SJohn Marino 265*e4b17023SJohn Marino #define VEC_reserve(T,A,V,R) \ 266*e4b17023SJohn Marino (VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO)) 267*e4b17023SJohn Marino 268*e4b17023SJohn Marino /* Reserve space exactly. 269*e4b17023SJohn Marino int VEC_T_A_reserve_exact(VEC(T,A) *&v, int reserve); 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino Ensure that V has at least RESERVE slots available. This will not 272*e4b17023SJohn Marino create additional headroom. Note this can cause V to be 273*e4b17023SJohn Marino reallocated. Returns nonzero iff reallocation actually 274*e4b17023SJohn Marino occurred. */ 275*e4b17023SJohn Marino 276*e4b17023SJohn Marino #define VEC_reserve_exact(T,A,V,R) \ 277*e4b17023SJohn Marino (VEC_OP(T,A,reserve_exact)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO)) 278*e4b17023SJohn Marino 279*e4b17023SJohn Marino /* Copy elements with no reallocation 280*e4b17023SJohn Marino void VEC_T_splice (VEC(T) *dst, VEC(T) *src); // Integer 281*e4b17023SJohn Marino void VEC_T_splice (VEC(T) *dst, VEC(T) *src); // Pointer 282*e4b17023SJohn Marino void VEC_T_splice (VEC(T) *dst, VEC(T) *src); // Object 283*e4b17023SJohn Marino 284*e4b17023SJohn Marino Copy the elements in SRC to the end of DST as if by memcpy. DST and 285*e4b17023SJohn Marino SRC need not be allocated with the same mechanism, although they most 286*e4b17023SJohn Marino often will be. DST is assumed to have sufficient headroom 287*e4b17023SJohn Marino available. */ 288*e4b17023SJohn Marino 289*e4b17023SJohn Marino #define VEC_splice(T,DST,SRC) \ 290*e4b17023SJohn Marino (VEC_OP(T,base,splice)(VEC_BASE(DST), VEC_BASE(SRC) VEC_CHECK_INFO)) 291*e4b17023SJohn Marino 292*e4b17023SJohn Marino /* Copy elements with reallocation 293*e4b17023SJohn Marino void VEC_T_safe_splice (VEC(T,A) *&dst, VEC(T) *src); // Integer 294*e4b17023SJohn Marino void VEC_T_safe_splice (VEC(T,A) *&dst, VEC(T) *src); // Pointer 295*e4b17023SJohn Marino void VEC_T_safe_splice (VEC(T,A) *&dst, VEC(T) *src); // Object 296*e4b17023SJohn Marino 297*e4b17023SJohn Marino Copy the elements in SRC to the end of DST as if by memcpy. DST and 298*e4b17023SJohn Marino SRC need not be allocated with the same mechanism, although they most 299*e4b17023SJohn Marino often will be. DST need not have sufficient headroom and will be 300*e4b17023SJohn Marino reallocated if needed. */ 301*e4b17023SJohn Marino 302*e4b17023SJohn Marino #define VEC_safe_splice(T,A,DST,SRC) \ 303*e4b17023SJohn Marino (VEC_OP(T,A,safe_splice)(&(DST), VEC_BASE(SRC) VEC_CHECK_INFO MEM_STAT_INFO)) 304*e4b17023SJohn Marino 305*e4b17023SJohn Marino /* Push object with no reallocation 306*e4b17023SJohn Marino T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer 307*e4b17023SJohn Marino T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer 308*e4b17023SJohn Marino T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object 309*e4b17023SJohn Marino 310*e4b17023SJohn Marino Push a new element onto the end, returns a pointer to the slot 311*e4b17023SJohn Marino filled in. For object vectors, the new value can be NULL, in which 312*e4b17023SJohn Marino case NO initialization is performed. There must 313*e4b17023SJohn Marino be sufficient space in the vector. */ 314*e4b17023SJohn Marino 315*e4b17023SJohn Marino #define VEC_quick_push(T,V,O) \ 316*e4b17023SJohn Marino (VEC_OP(T,base,quick_push)(VEC_BASE(V),O VEC_CHECK_INFO)) 317*e4b17023SJohn Marino 318*e4b17023SJohn Marino /* Push object with reallocation 319*e4b17023SJohn Marino T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Integer 320*e4b17023SJohn Marino T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Pointer 321*e4b17023SJohn Marino T *VEC_T_A_safe_push (VEC(T,A) *&v, T *obj); // Object 322*e4b17023SJohn Marino 323*e4b17023SJohn Marino Push a new element onto the end, returns a pointer to the slot 324*e4b17023SJohn Marino filled in. For object vectors, the new value can be NULL, in which 325*e4b17023SJohn Marino case NO initialization is performed. Reallocates V, if needed. */ 326*e4b17023SJohn Marino 327*e4b17023SJohn Marino #define VEC_safe_push(T,A,V,O) \ 328*e4b17023SJohn Marino (VEC_OP(T,A,safe_push)(&(V),O VEC_CHECK_INFO MEM_STAT_INFO)) 329*e4b17023SJohn Marino 330*e4b17023SJohn Marino /* Pop element off end 331*e4b17023SJohn Marino T VEC_T_pop (VEC(T) *v); // Integer 332*e4b17023SJohn Marino T VEC_T_pop (VEC(T) *v); // Pointer 333*e4b17023SJohn Marino void VEC_T_pop (VEC(T) *v); // Object 334*e4b17023SJohn Marino 335*e4b17023SJohn Marino Pop the last element off the end. Returns the element popped, for 336*e4b17023SJohn Marino pointer vectors. */ 337*e4b17023SJohn Marino 338*e4b17023SJohn Marino #define VEC_pop(T,V) (VEC_OP(T,base,pop)(VEC_BASE(V) VEC_CHECK_INFO)) 339*e4b17023SJohn Marino 340*e4b17023SJohn Marino /* Truncate to specific length 341*e4b17023SJohn Marino void VEC_T_truncate (VEC(T) *v, unsigned len); 342*e4b17023SJohn Marino 343*e4b17023SJohn Marino Set the length as specified. The new length must be less than or 344*e4b17023SJohn Marino equal to the current length. This is an O(1) operation. */ 345*e4b17023SJohn Marino 346*e4b17023SJohn Marino #define VEC_truncate(T,V,I) \ 347*e4b17023SJohn Marino (VEC_OP(T,base,truncate)(VEC_BASE(V),I VEC_CHECK_INFO)) 348*e4b17023SJohn Marino 349*e4b17023SJohn Marino /* Grow to a specific length. 350*e4b17023SJohn Marino void VEC_T_A_safe_grow (VEC(T,A) *&v, int len); 351*e4b17023SJohn Marino 352*e4b17023SJohn Marino Grow the vector to a specific length. The LEN must be as 353*e4b17023SJohn Marino long or longer than the current length. The new elements are 354*e4b17023SJohn Marino uninitialized. */ 355*e4b17023SJohn Marino 356*e4b17023SJohn Marino #define VEC_safe_grow(T,A,V,I) \ 357*e4b17023SJohn Marino (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO MEM_STAT_INFO)) 358*e4b17023SJohn Marino 359*e4b17023SJohn Marino /* Grow to a specific length. 360*e4b17023SJohn Marino void VEC_T_A_safe_grow_cleared (VEC(T,A) *&v, int len); 361*e4b17023SJohn Marino 362*e4b17023SJohn Marino Grow the vector to a specific length. The LEN must be as 363*e4b17023SJohn Marino long or longer than the current length. The new elements are 364*e4b17023SJohn Marino initialized to zero. */ 365*e4b17023SJohn Marino 366*e4b17023SJohn Marino #define VEC_safe_grow_cleared(T,A,V,I) \ 367*e4b17023SJohn Marino (VEC_OP(T,A,safe_grow_cleared)(&(V),I VEC_CHECK_INFO MEM_STAT_INFO)) 368*e4b17023SJohn Marino 369*e4b17023SJohn Marino /* Replace element 370*e4b17023SJohn Marino T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Integer 371*e4b17023SJohn Marino T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Pointer 372*e4b17023SJohn Marino T *VEC_T_replace (VEC(T) *v, unsigned ix, T *val); // Object 373*e4b17023SJohn Marino 374*e4b17023SJohn Marino Replace the IXth element of V with a new value, VAL. For pointer 375*e4b17023SJohn Marino vectors returns the original value. For object vectors returns a 376*e4b17023SJohn Marino pointer to the new value. For object vectors the new value can be 377*e4b17023SJohn Marino NULL, in which case no overwriting of the slot is actually 378*e4b17023SJohn Marino performed. */ 379*e4b17023SJohn Marino 380*e4b17023SJohn Marino #define VEC_replace(T,V,I,O) \ 381*e4b17023SJohn Marino (VEC_OP(T,base,replace)(VEC_BASE(V),I,O VEC_CHECK_INFO)) 382*e4b17023SJohn Marino 383*e4b17023SJohn Marino /* Insert object with no reallocation 384*e4b17023SJohn Marino T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Integer 385*e4b17023SJohn Marino T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer 386*e4b17023SJohn Marino T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object 387*e4b17023SJohn Marino 388*e4b17023SJohn Marino Insert an element, VAL, at the IXth position of V. Return a pointer 389*e4b17023SJohn Marino to the slot created. For vectors of object, the new value can be 390*e4b17023SJohn Marino NULL, in which case no initialization of the inserted slot takes 391*e4b17023SJohn Marino place. There must be sufficient space. */ 392*e4b17023SJohn Marino 393*e4b17023SJohn Marino #define VEC_quick_insert(T,V,I,O) \ 394*e4b17023SJohn Marino (VEC_OP(T,base,quick_insert)(VEC_BASE(V),I,O VEC_CHECK_INFO)) 395*e4b17023SJohn Marino 396*e4b17023SJohn Marino /* Insert object with reallocation 397*e4b17023SJohn Marino T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Integer 398*e4b17023SJohn Marino T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Pointer 399*e4b17023SJohn Marino T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T *val); // Object 400*e4b17023SJohn Marino 401*e4b17023SJohn Marino Insert an element, VAL, at the IXth position of V. Return a pointer 402*e4b17023SJohn Marino to the slot created. For vectors of object, the new value can be 403*e4b17023SJohn Marino NULL, in which case no initialization of the inserted slot takes 404*e4b17023SJohn Marino place. Reallocate V, if necessary. */ 405*e4b17023SJohn Marino 406*e4b17023SJohn Marino #define VEC_safe_insert(T,A,V,I,O) \ 407*e4b17023SJohn Marino (VEC_OP(T,A,safe_insert)(&(V),I,O VEC_CHECK_INFO MEM_STAT_INFO)) 408*e4b17023SJohn Marino 409*e4b17023SJohn Marino /* Remove element retaining order 410*e4b17023SJohn Marino T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Integer 411*e4b17023SJohn Marino T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer 412*e4b17023SJohn Marino void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Object 413*e4b17023SJohn Marino 414*e4b17023SJohn Marino Remove an element from the IXth position of V. Ordering of 415*e4b17023SJohn Marino remaining elements is preserved. For pointer vectors returns the 416*e4b17023SJohn Marino removed object. This is an O(N) operation due to a memmove. */ 417*e4b17023SJohn Marino 418*e4b17023SJohn Marino #define VEC_ordered_remove(T,V,I) \ 419*e4b17023SJohn Marino (VEC_OP(T,base,ordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO)) 420*e4b17023SJohn Marino 421*e4b17023SJohn Marino /* Remove element destroying order 422*e4b17023SJohn Marino T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Integer 423*e4b17023SJohn Marino T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer 424*e4b17023SJohn Marino void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Object 425*e4b17023SJohn Marino 426*e4b17023SJohn Marino Remove an element from the IXth position of V. Ordering of 427*e4b17023SJohn Marino remaining elements is destroyed. For pointer vectors returns the 428*e4b17023SJohn Marino removed object. This is an O(1) operation. */ 429*e4b17023SJohn Marino 430*e4b17023SJohn Marino #define VEC_unordered_remove(T,V,I) \ 431*e4b17023SJohn Marino (VEC_OP(T,base,unordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO)) 432*e4b17023SJohn Marino 433*e4b17023SJohn Marino /* Remove a block of elements 434*e4b17023SJohn Marino void VEC_T_block_remove (VEC(T) *v, unsigned ix, unsigned len); 435*e4b17023SJohn Marino 436*e4b17023SJohn Marino Remove LEN elements starting at the IXth. Ordering is retained. 437*e4b17023SJohn Marino This is an O(N) operation due to memmove. */ 438*e4b17023SJohn Marino 439*e4b17023SJohn Marino #define VEC_block_remove(T,V,I,L) \ 440*e4b17023SJohn Marino (VEC_OP(T,base,block_remove)(VEC_BASE(V),I,L VEC_CHECK_INFO)) 441*e4b17023SJohn Marino 442*e4b17023SJohn Marino /* Get the address of the array of elements 443*e4b17023SJohn Marino T *VEC_T_address (VEC(T) v) 444*e4b17023SJohn Marino 445*e4b17023SJohn Marino If you need to directly manipulate the array (for instance, you 446*e4b17023SJohn Marino want to feed it to qsort), use this accessor. */ 447*e4b17023SJohn Marino 448*e4b17023SJohn Marino #define VEC_address(T,V) (VEC_OP(T,base,address)(VEC_BASE(V))) 449*e4b17023SJohn Marino 450*e4b17023SJohn Marino /* Conveniently sort the contents of the vector with qsort. 451*e4b17023SJohn Marino void VEC_qsort (VEC(T) *v, int (*cmp_func)(const void *, const void *)) */ 452*e4b17023SJohn Marino 453*e4b17023SJohn Marino #define VEC_qsort(T,V,CMP) qsort(VEC_address (T,V), VEC_length(T,V), \ 454*e4b17023SJohn Marino sizeof (T), CMP) 455*e4b17023SJohn Marino 456*e4b17023SJohn Marino /* Find the first index in the vector not less than the object. 457*e4b17023SJohn Marino unsigned VEC_T_lower_bound (VEC(T) *v, const T val, 458*e4b17023SJohn Marino bool (*lessthan) (const T, const T)); // Integer 459*e4b17023SJohn Marino unsigned VEC_T_lower_bound (VEC(T) *v, const T val, 460*e4b17023SJohn Marino bool (*lessthan) (const T, const T)); // Pointer 461*e4b17023SJohn Marino unsigned VEC_T_lower_bound (VEC(T) *v, const T *val, 462*e4b17023SJohn Marino bool (*lessthan) (const T*, const T*)); // Object 463*e4b17023SJohn Marino 464*e4b17023SJohn Marino Find the first position in which VAL could be inserted without 465*e4b17023SJohn Marino changing the ordering of V. LESSTHAN is a function that returns 466*e4b17023SJohn Marino true if the first argument is strictly less than the second. */ 467*e4b17023SJohn Marino 468*e4b17023SJohn Marino #define VEC_lower_bound(T,V,O,LT) \ 469*e4b17023SJohn Marino (VEC_OP(T,base,lower_bound)(VEC_BASE(V),O,LT VEC_CHECK_INFO)) 470*e4b17023SJohn Marino 471*e4b17023SJohn Marino /* Reallocate an array of elements with prefix. */ 472*e4b17023SJohn Marino extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL); 473*e4b17023SJohn Marino extern void *vec_gc_p_reserve_exact (void *, int MEM_STAT_DECL); 474*e4b17023SJohn Marino extern void *vec_gc_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL); 475*e4b17023SJohn Marino extern void *vec_gc_o_reserve_exact (void *, int, size_t, size_t 476*e4b17023SJohn Marino MEM_STAT_DECL); 477*e4b17023SJohn Marino extern void ggc_free (void *); 478*e4b17023SJohn Marino #define vec_gc_free(V) ggc_free (V) 479*e4b17023SJohn Marino extern void *vec_heap_p_reserve (void *, int MEM_STAT_DECL); 480*e4b17023SJohn Marino extern void *vec_heap_p_reserve_exact (void *, int MEM_STAT_DECL); 481*e4b17023SJohn Marino extern void *vec_heap_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL); 482*e4b17023SJohn Marino extern void *vec_heap_o_reserve_exact (void *, int, size_t, size_t 483*e4b17023SJohn Marino MEM_STAT_DECL); 484*e4b17023SJohn Marino extern void dump_vec_loc_statistics (void); 485*e4b17023SJohn Marino #ifdef GATHER_STATISTICS 486*e4b17023SJohn Marino void vec_heap_free (void *); 487*e4b17023SJohn Marino #else 488*e4b17023SJohn Marino /* Avoid problems with frontends that #define free(x). */ 489*e4b17023SJohn Marino #define vec_heap_free(V) (free) (V) 490*e4b17023SJohn Marino #endif 491*e4b17023SJohn Marino 492*e4b17023SJohn Marino #if ENABLE_CHECKING 493*e4b17023SJohn Marino #define VEC_CHECK_INFO ,__FILE__,__LINE__,__FUNCTION__ 494*e4b17023SJohn Marino #define VEC_CHECK_DECL ,const char *file_,unsigned line_,const char *function_ 495*e4b17023SJohn Marino #define VEC_CHECK_PASS ,file_,line_,function_ 496*e4b17023SJohn Marino 497*e4b17023SJohn Marino #define VEC_ASSERT(EXPR,OP,T,A) \ 498*e4b17023SJohn Marino (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(T,A)), 0)) 499*e4b17023SJohn Marino 500*e4b17023SJohn Marino extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL) 501*e4b17023SJohn Marino ATTRIBUTE_NORETURN; 502*e4b17023SJohn Marino #define VEC_ASSERT_FAIL(OP,VEC) vec_assert_fail (OP,#VEC VEC_CHECK_PASS) 503*e4b17023SJohn Marino #else 504*e4b17023SJohn Marino #define VEC_CHECK_INFO 505*e4b17023SJohn Marino #define VEC_CHECK_DECL 506*e4b17023SJohn Marino #define VEC_CHECK_PASS 507*e4b17023SJohn Marino #define VEC_ASSERT(EXPR,OP,T,A) (void)(EXPR) 508*e4b17023SJohn Marino #endif 509*e4b17023SJohn Marino 510*e4b17023SJohn Marino /* Note: gengtype has hardwired knowledge of the expansions of the 511*e4b17023SJohn Marino VEC, DEF_VEC_*, and DEF_VEC_ALLOC_* macros. If you change the 512*e4b17023SJohn Marino expansions of these macros you may need to change gengtype too. */ 513*e4b17023SJohn Marino 514*e4b17023SJohn Marino typedef struct GTY(()) vec_prefix 515*e4b17023SJohn Marino { 516*e4b17023SJohn Marino unsigned num; 517*e4b17023SJohn Marino unsigned alloc; 518*e4b17023SJohn Marino } vec_prefix; 519*e4b17023SJohn Marino 520*e4b17023SJohn Marino #define VEC(T,A) VEC_##T##_##A 521*e4b17023SJohn Marino #define VEC_OP(T,A,OP) VEC_##T##_##A##_##OP 522*e4b17023SJohn Marino 523*e4b17023SJohn Marino /* Base of vector type, not user visible. */ 524*e4b17023SJohn Marino #define VEC_T(T,B) \ 525*e4b17023SJohn Marino typedef struct VEC(T,B) \ 526*e4b17023SJohn Marino { \ 527*e4b17023SJohn Marino struct vec_prefix prefix; \ 528*e4b17023SJohn Marino T vec[1]; \ 529*e4b17023SJohn Marino } VEC(T,B) 530*e4b17023SJohn Marino 531*e4b17023SJohn Marino #define VEC_T_GTY(T,B) \ 532*e4b17023SJohn Marino typedef struct GTY(()) VEC(T,B) \ 533*e4b17023SJohn Marino { \ 534*e4b17023SJohn Marino struct vec_prefix prefix; \ 535*e4b17023SJohn Marino T GTY ((length ("%h.prefix.num"))) vec[1]; \ 536*e4b17023SJohn Marino } VEC(T,B) 537*e4b17023SJohn Marino 538*e4b17023SJohn Marino /* Derived vector type, user visible. */ 539*e4b17023SJohn Marino #define VEC_TA_GTY(T,B,A,GTY) \ 540*e4b17023SJohn Marino typedef struct GTY VEC(T,A) \ 541*e4b17023SJohn Marino { \ 542*e4b17023SJohn Marino VEC(T,B) base; \ 543*e4b17023SJohn Marino } VEC(T,A) 544*e4b17023SJohn Marino 545*e4b17023SJohn Marino #define VEC_TA(T,B,A) \ 546*e4b17023SJohn Marino typedef struct VEC(T,A) \ 547*e4b17023SJohn Marino { \ 548*e4b17023SJohn Marino VEC(T,B) base; \ 549*e4b17023SJohn Marino } VEC(T,A) 550*e4b17023SJohn Marino 551*e4b17023SJohn Marino /* Convert to base type. */ 552*e4b17023SJohn Marino #if GCC_VERSION >= 4000 553*e4b17023SJohn Marino #define VEC_BASE(P) \ 554*e4b17023SJohn Marino ((offsetof (__typeof (*P), base) == 0 || (P)) ? &(P)->base : 0) 555*e4b17023SJohn Marino #else 556*e4b17023SJohn Marino #define VEC_BASE(P) ((P) ? &(P)->base : 0) 557*e4b17023SJohn Marino #endif 558*e4b17023SJohn Marino 559*e4b17023SJohn Marino /* Vector of integer-like object. */ 560*e4b17023SJohn Marino #define DEF_VEC_I(T) \ 561*e4b17023SJohn Marino static inline void VEC_OP (T,must_be,integral_type) (void) \ 562*e4b17023SJohn Marino { \ 563*e4b17023SJohn Marino (void)~(T)0; \ 564*e4b17023SJohn Marino } \ 565*e4b17023SJohn Marino \ 566*e4b17023SJohn Marino VEC_T(T,base); \ 567*e4b17023SJohn Marino VEC_TA(T,base,none); \ 568*e4b17023SJohn Marino DEF_VEC_FUNC_P(T) \ 569*e4b17023SJohn Marino struct vec_swallow_trailing_semi 570*e4b17023SJohn Marino #define DEF_VEC_ALLOC_I(T,A) \ 571*e4b17023SJohn Marino VEC_TA(T,base,A); \ 572*e4b17023SJohn Marino DEF_VEC_ALLOC_FUNC_I(T,A) \ 573*e4b17023SJohn Marino DEF_VEC_NONALLOC_FUNCS_I(T,A) \ 574*e4b17023SJohn Marino struct vec_swallow_trailing_semi 575*e4b17023SJohn Marino 576*e4b17023SJohn Marino /* Vector of pointer to object. */ 577*e4b17023SJohn Marino #define DEF_VEC_P(T) \ 578*e4b17023SJohn Marino static inline void VEC_OP (T,must_be,pointer_type) (void) \ 579*e4b17023SJohn Marino { \ 580*e4b17023SJohn Marino (void)((T)1 == (void *)1); \ 581*e4b17023SJohn Marino } \ 582*e4b17023SJohn Marino \ 583*e4b17023SJohn Marino VEC_T_GTY(T,base); \ 584*e4b17023SJohn Marino VEC_TA(T,base,none); \ 585*e4b17023SJohn Marino DEF_VEC_FUNC_P(T) \ 586*e4b17023SJohn Marino struct vec_swallow_trailing_semi 587*e4b17023SJohn Marino #define DEF_VEC_ALLOC_P(T,A) \ 588*e4b17023SJohn Marino VEC_TA(T,base,A); \ 589*e4b17023SJohn Marino DEF_VEC_ALLOC_FUNC_P(T,A) \ 590*e4b17023SJohn Marino DEF_VEC_NONALLOC_FUNCS_P(T,A) \ 591*e4b17023SJohn Marino struct vec_swallow_trailing_semi 592*e4b17023SJohn Marino 593*e4b17023SJohn Marino #define DEF_VEC_FUNC_P(T) \ 594*e4b17023SJohn Marino static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \ 595*e4b17023SJohn Marino { \ 596*e4b17023SJohn Marino return vec_ ? vec_->prefix.num : 0; \ 597*e4b17023SJohn Marino } \ 598*e4b17023SJohn Marino \ 599*e4b17023SJohn Marino static inline T VEC_OP (T,base,last) \ 600*e4b17023SJohn Marino (const VEC(T,base) *vec_ VEC_CHECK_DECL) \ 601*e4b17023SJohn Marino { \ 602*e4b17023SJohn Marino VEC_ASSERT (vec_ && vec_->prefix.num, "last", T, base); \ 603*e4b17023SJohn Marino \ 604*e4b17023SJohn Marino return vec_->vec[vec_->prefix.num - 1]; \ 605*e4b17023SJohn Marino } \ 606*e4b17023SJohn Marino \ 607*e4b17023SJohn Marino static inline T VEC_OP (T,base,index) \ 608*e4b17023SJohn Marino (const VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \ 609*e4b17023SJohn Marino { \ 610*e4b17023SJohn Marino VEC_ASSERT (vec_ && ix_ < vec_->prefix.num, "index", T, base); \ 611*e4b17023SJohn Marino \ 612*e4b17023SJohn Marino return vec_->vec[ix_]; \ 613*e4b17023SJohn Marino } \ 614*e4b17023SJohn Marino \ 615*e4b17023SJohn Marino static inline int VEC_OP (T,base,iterate) \ 616*e4b17023SJohn Marino (const VEC(T,base) *vec_, unsigned ix_, T *ptr) \ 617*e4b17023SJohn Marino { \ 618*e4b17023SJohn Marino if (vec_ && ix_ < vec_->prefix.num) \ 619*e4b17023SJohn Marino { \ 620*e4b17023SJohn Marino *ptr = vec_->vec[ix_]; \ 621*e4b17023SJohn Marino return 1; \ 622*e4b17023SJohn Marino } \ 623*e4b17023SJohn Marino else \ 624*e4b17023SJohn Marino { \ 625*e4b17023SJohn Marino *ptr = (T) 0; \ 626*e4b17023SJohn Marino return 0; \ 627*e4b17023SJohn Marino } \ 628*e4b17023SJohn Marino } \ 629*e4b17023SJohn Marino \ 630*e4b17023SJohn Marino static inline size_t VEC_OP (T,base,embedded_size) \ 631*e4b17023SJohn Marino (int alloc_) \ 632*e4b17023SJohn Marino { \ 633*e4b17023SJohn Marino return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \ 634*e4b17023SJohn Marino } \ 635*e4b17023SJohn Marino \ 636*e4b17023SJohn Marino static inline void VEC_OP (T,base,embedded_init) \ 637*e4b17023SJohn Marino (VEC(T,base) *vec_, int alloc_) \ 638*e4b17023SJohn Marino { \ 639*e4b17023SJohn Marino vec_->prefix.num = 0; \ 640*e4b17023SJohn Marino vec_->prefix.alloc = alloc_; \ 641*e4b17023SJohn Marino } \ 642*e4b17023SJohn Marino \ 643*e4b17023SJohn Marino static inline int VEC_OP (T,base,space) \ 644*e4b17023SJohn Marino (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL) \ 645*e4b17023SJohn Marino { \ 646*e4b17023SJohn Marino VEC_ASSERT (alloc_ >= 0, "space", T, base); \ 647*e4b17023SJohn Marino return vec_ ? vec_->prefix.alloc - vec_->prefix.num >= (unsigned)alloc_ : !alloc_; \ 648*e4b17023SJohn Marino } \ 649*e4b17023SJohn Marino \ 650*e4b17023SJohn Marino static inline void VEC_OP(T,base,splice) \ 651*e4b17023SJohn Marino (VEC(T,base) *dst_, VEC(T,base) *src_ VEC_CHECK_DECL) \ 652*e4b17023SJohn Marino { \ 653*e4b17023SJohn Marino if (src_) \ 654*e4b17023SJohn Marino { \ 655*e4b17023SJohn Marino unsigned len_ = src_->prefix.num; \ 656*e4b17023SJohn Marino VEC_ASSERT (dst_->prefix.num + len_ <= dst_->prefix.alloc, "splice", T, base); \ 657*e4b17023SJohn Marino \ 658*e4b17023SJohn Marino memcpy (&dst_->vec[dst_->prefix.num], &src_->vec[0], len_ * sizeof (T)); \ 659*e4b17023SJohn Marino dst_->prefix.num += len_; \ 660*e4b17023SJohn Marino } \ 661*e4b17023SJohn Marino } \ 662*e4b17023SJohn Marino \ 663*e4b17023SJohn Marino static inline T *VEC_OP (T,base,quick_push) \ 664*e4b17023SJohn Marino (VEC(T,base) *vec_, T obj_ VEC_CHECK_DECL) \ 665*e4b17023SJohn Marino { \ 666*e4b17023SJohn Marino T *slot_; \ 667*e4b17023SJohn Marino \ 668*e4b17023SJohn Marino VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base); \ 669*e4b17023SJohn Marino slot_ = &vec_->vec[vec_->prefix.num++]; \ 670*e4b17023SJohn Marino *slot_ = obj_; \ 671*e4b17023SJohn Marino \ 672*e4b17023SJohn Marino return slot_; \ 673*e4b17023SJohn Marino } \ 674*e4b17023SJohn Marino \ 675*e4b17023SJohn Marino static inline T VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \ 676*e4b17023SJohn Marino { \ 677*e4b17023SJohn Marino T obj_; \ 678*e4b17023SJohn Marino \ 679*e4b17023SJohn Marino VEC_ASSERT (vec_->prefix.num, "pop", T, base); \ 680*e4b17023SJohn Marino obj_ = vec_->vec[--vec_->prefix.num]; \ 681*e4b17023SJohn Marino \ 682*e4b17023SJohn Marino return obj_; \ 683*e4b17023SJohn Marino } \ 684*e4b17023SJohn Marino \ 685*e4b17023SJohn Marino static inline void VEC_OP (T,base,truncate) \ 686*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL) \ 687*e4b17023SJohn Marino { \ 688*e4b17023SJohn Marino VEC_ASSERT (vec_ ? vec_->prefix.num >= size_ : !size_, "truncate", T, base); \ 689*e4b17023SJohn Marino if (vec_) \ 690*e4b17023SJohn Marino vec_->prefix.num = size_; \ 691*e4b17023SJohn Marino } \ 692*e4b17023SJohn Marino \ 693*e4b17023SJohn Marino static inline T VEC_OP (T,base,replace) \ 694*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \ 695*e4b17023SJohn Marino { \ 696*e4b17023SJohn Marino T old_obj_; \ 697*e4b17023SJohn Marino \ 698*e4b17023SJohn Marino VEC_ASSERT (ix_ < vec_->prefix.num, "replace", T, base); \ 699*e4b17023SJohn Marino old_obj_ = vec_->vec[ix_]; \ 700*e4b17023SJohn Marino vec_->vec[ix_] = obj_; \ 701*e4b17023SJohn Marino \ 702*e4b17023SJohn Marino return old_obj_; \ 703*e4b17023SJohn Marino } \ 704*e4b17023SJohn Marino \ 705*e4b17023SJohn Marino static inline T *VEC_OP (T,base,quick_insert) \ 706*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \ 707*e4b17023SJohn Marino { \ 708*e4b17023SJohn Marino T *slot_; \ 709*e4b17023SJohn Marino \ 710*e4b17023SJohn Marino VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "insert", T, base); \ 711*e4b17023SJohn Marino VEC_ASSERT (ix_ <= vec_->prefix.num, "insert", T, base); \ 712*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 713*e4b17023SJohn Marino memmove (slot_ + 1, slot_, (vec_->prefix.num++ - ix_) * sizeof (T)); \ 714*e4b17023SJohn Marino *slot_ = obj_; \ 715*e4b17023SJohn Marino \ 716*e4b17023SJohn Marino return slot_; \ 717*e4b17023SJohn Marino } \ 718*e4b17023SJohn Marino \ 719*e4b17023SJohn Marino static inline T VEC_OP (T,base,ordered_remove) \ 720*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \ 721*e4b17023SJohn Marino { \ 722*e4b17023SJohn Marino T *slot_; \ 723*e4b17023SJohn Marino T obj_; \ 724*e4b17023SJohn Marino \ 725*e4b17023SJohn Marino VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base); \ 726*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 727*e4b17023SJohn Marino obj_ = *slot_; \ 728*e4b17023SJohn Marino memmove (slot_, slot_ + 1, (--vec_->prefix.num - ix_) * sizeof (T)); \ 729*e4b17023SJohn Marino \ 730*e4b17023SJohn Marino return obj_; \ 731*e4b17023SJohn Marino } \ 732*e4b17023SJohn Marino \ 733*e4b17023SJohn Marino static inline T VEC_OP (T,base,unordered_remove) \ 734*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \ 735*e4b17023SJohn Marino { \ 736*e4b17023SJohn Marino T *slot_; \ 737*e4b17023SJohn Marino T obj_; \ 738*e4b17023SJohn Marino \ 739*e4b17023SJohn Marino VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base); \ 740*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 741*e4b17023SJohn Marino obj_ = *slot_; \ 742*e4b17023SJohn Marino *slot_ = vec_->vec[--vec_->prefix.num]; \ 743*e4b17023SJohn Marino \ 744*e4b17023SJohn Marino return obj_; \ 745*e4b17023SJohn Marino } \ 746*e4b17023SJohn Marino \ 747*e4b17023SJohn Marino static inline void VEC_OP (T,base,block_remove) \ 748*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL) \ 749*e4b17023SJohn Marino { \ 750*e4b17023SJohn Marino T *slot_; \ 751*e4b17023SJohn Marino \ 752*e4b17023SJohn Marino VEC_ASSERT (ix_ + len_ <= vec_->prefix.num, "block_remove", T, base); \ 753*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 754*e4b17023SJohn Marino vec_->prefix.num -= len_; \ 755*e4b17023SJohn Marino memmove (slot_, slot_ + len_, (vec_->prefix.num - ix_) * sizeof (T)); \ 756*e4b17023SJohn Marino } \ 757*e4b17023SJohn Marino \ 758*e4b17023SJohn Marino static inline T *VEC_OP (T,base,address) \ 759*e4b17023SJohn Marino (VEC(T,base) *vec_) \ 760*e4b17023SJohn Marino { \ 761*e4b17023SJohn Marino return vec_ ? vec_->vec : 0; \ 762*e4b17023SJohn Marino } \ 763*e4b17023SJohn Marino \ 764*e4b17023SJohn Marino static inline unsigned VEC_OP (T,base,lower_bound) \ 765*e4b17023SJohn Marino (VEC(T,base) *vec_, const T obj_, \ 766*e4b17023SJohn Marino bool (*lessthan_)(const T, const T) VEC_CHECK_DECL) \ 767*e4b17023SJohn Marino { \ 768*e4b17023SJohn Marino unsigned int len_ = VEC_OP (T,base, length) (vec_); \ 769*e4b17023SJohn Marino unsigned int half_, middle_; \ 770*e4b17023SJohn Marino unsigned int first_ = 0; \ 771*e4b17023SJohn Marino while (len_ > 0) \ 772*e4b17023SJohn Marino { \ 773*e4b17023SJohn Marino T middle_elem_; \ 774*e4b17023SJohn Marino half_ = len_ >> 1; \ 775*e4b17023SJohn Marino middle_ = first_; \ 776*e4b17023SJohn Marino middle_ += half_; \ 777*e4b17023SJohn Marino middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \ 778*e4b17023SJohn Marino if (lessthan_ (middle_elem_, obj_)) \ 779*e4b17023SJohn Marino { \ 780*e4b17023SJohn Marino first_ = middle_; \ 781*e4b17023SJohn Marino ++first_; \ 782*e4b17023SJohn Marino len_ = len_ - half_ - 1; \ 783*e4b17023SJohn Marino } \ 784*e4b17023SJohn Marino else \ 785*e4b17023SJohn Marino len_ = half_; \ 786*e4b17023SJohn Marino } \ 787*e4b17023SJohn Marino return first_; \ 788*e4b17023SJohn Marino } 789*e4b17023SJohn Marino 790*e4b17023SJohn Marino #define DEF_VEC_ALLOC_FUNC_P(T,A) \ 791*e4b17023SJohn Marino static inline VEC(T,A) *VEC_OP (T,A,alloc) \ 792*e4b17023SJohn Marino (int alloc_ MEM_STAT_DECL) \ 793*e4b17023SJohn Marino { \ 794*e4b17023SJohn Marino return (VEC(T,A) *) vec_##A##_p_reserve_exact (NULL, alloc_ \ 795*e4b17023SJohn Marino PASS_MEM_STAT); \ 796*e4b17023SJohn Marino } 797*e4b17023SJohn Marino 798*e4b17023SJohn Marino 799*e4b17023SJohn Marino #define DEF_VEC_NONALLOC_FUNCS_P(T,A) \ 800*e4b17023SJohn Marino static inline void VEC_OP (T,A,free) \ 801*e4b17023SJohn Marino (VEC(T,A) **vec_) \ 802*e4b17023SJohn Marino { \ 803*e4b17023SJohn Marino if (*vec_) \ 804*e4b17023SJohn Marino vec_##A##_free (*vec_); \ 805*e4b17023SJohn Marino *vec_ = NULL; \ 806*e4b17023SJohn Marino } \ 807*e4b17023SJohn Marino \ 808*e4b17023SJohn Marino static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \ 809*e4b17023SJohn Marino { \ 810*e4b17023SJohn Marino size_t len_ = vec_ ? vec_->prefix.num : 0; \ 811*e4b17023SJohn Marino VEC (T,A) *new_vec_ = NULL; \ 812*e4b17023SJohn Marino \ 813*e4b17023SJohn Marino if (len_) \ 814*e4b17023SJohn Marino { \ 815*e4b17023SJohn Marino new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve_exact \ 816*e4b17023SJohn Marino (NULL, len_ PASS_MEM_STAT)); \ 817*e4b17023SJohn Marino \ 818*e4b17023SJohn Marino new_vec_->base.prefix.num = len_; \ 819*e4b17023SJohn Marino memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \ 820*e4b17023SJohn Marino } \ 821*e4b17023SJohn Marino return new_vec_; \ 822*e4b17023SJohn Marino } \ 823*e4b17023SJohn Marino \ 824*e4b17023SJohn Marino static inline int VEC_OP (T,A,reserve) \ 825*e4b17023SJohn Marino (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \ 826*e4b17023SJohn Marino { \ 827*e4b17023SJohn Marino int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \ 828*e4b17023SJohn Marino VEC_CHECK_PASS); \ 829*e4b17023SJohn Marino \ 830*e4b17023SJohn Marino if (extend) \ 831*e4b17023SJohn Marino *vec_ = (VEC(T,A) *) vec_##A##_p_reserve (*vec_, alloc_ PASS_MEM_STAT); \ 832*e4b17023SJohn Marino \ 833*e4b17023SJohn Marino return extend; \ 834*e4b17023SJohn Marino } \ 835*e4b17023SJohn Marino \ 836*e4b17023SJohn Marino static inline int VEC_OP (T,A,reserve_exact) \ 837*e4b17023SJohn Marino (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \ 838*e4b17023SJohn Marino { \ 839*e4b17023SJohn Marino int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \ 840*e4b17023SJohn Marino VEC_CHECK_PASS); \ 841*e4b17023SJohn Marino \ 842*e4b17023SJohn Marino if (extend) \ 843*e4b17023SJohn Marino *vec_ = (VEC(T,A) *) vec_##A##_p_reserve_exact (*vec_, alloc_ \ 844*e4b17023SJohn Marino PASS_MEM_STAT); \ 845*e4b17023SJohn Marino \ 846*e4b17023SJohn Marino return extend; \ 847*e4b17023SJohn Marino } \ 848*e4b17023SJohn Marino \ 849*e4b17023SJohn Marino static inline void VEC_OP (T,A,safe_grow) \ 850*e4b17023SJohn Marino (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \ 851*e4b17023SJohn Marino { \ 852*e4b17023SJohn Marino VEC_ASSERT (size_ >= 0 \ 853*e4b17023SJohn Marino && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \ 854*e4b17023SJohn Marino "grow", T, A); \ 855*e4b17023SJohn Marino VEC_OP (T,A,reserve_exact) (vec_, \ 856*e4b17023SJohn Marino size_ - (int)(*vec_ ? VEC_BASE(*vec_)->prefix.num : 0) \ 857*e4b17023SJohn Marino VEC_CHECK_PASS PASS_MEM_STAT); \ 858*e4b17023SJohn Marino VEC_BASE (*vec_)->prefix.num = size_; \ 859*e4b17023SJohn Marino } \ 860*e4b17023SJohn Marino \ 861*e4b17023SJohn Marino static inline void VEC_OP (T,A,safe_grow_cleared) \ 862*e4b17023SJohn Marino (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \ 863*e4b17023SJohn Marino { \ 864*e4b17023SJohn Marino int oldsize = VEC_OP(T,base,length) VEC_BASE(*vec_); \ 865*e4b17023SJohn Marino VEC_OP (T,A,safe_grow) (vec_, size_ VEC_CHECK_PASS PASS_MEM_STAT); \ 866*e4b17023SJohn Marino memset (&(VEC_OP (T,base,address) VEC_BASE(*vec_))[oldsize], 0, \ 867*e4b17023SJohn Marino sizeof (T) * (size_ - oldsize)); \ 868*e4b17023SJohn Marino } \ 869*e4b17023SJohn Marino \ 870*e4b17023SJohn Marino static inline void VEC_OP(T,A,safe_splice) \ 871*e4b17023SJohn Marino (VEC(T,A) **dst_, VEC(T,base) *src_ VEC_CHECK_DECL MEM_STAT_DECL) \ 872*e4b17023SJohn Marino { \ 873*e4b17023SJohn Marino if (src_) \ 874*e4b17023SJohn Marino { \ 875*e4b17023SJohn Marino VEC_OP (T,A,reserve_exact) (dst_, src_->prefix.num \ 876*e4b17023SJohn Marino VEC_CHECK_PASS MEM_STAT_INFO); \ 877*e4b17023SJohn Marino \ 878*e4b17023SJohn Marino VEC_OP (T,base,splice) (VEC_BASE (*dst_), src_ \ 879*e4b17023SJohn Marino VEC_CHECK_PASS); \ 880*e4b17023SJohn Marino } \ 881*e4b17023SJohn Marino } \ 882*e4b17023SJohn Marino \ 883*e4b17023SJohn Marino static inline T *VEC_OP (T,A,safe_push) \ 884*e4b17023SJohn Marino (VEC(T,A) **vec_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \ 885*e4b17023SJohn Marino { \ 886*e4b17023SJohn Marino VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \ 887*e4b17023SJohn Marino \ 888*e4b17023SJohn Marino return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \ 889*e4b17023SJohn Marino } \ 890*e4b17023SJohn Marino \ 891*e4b17023SJohn Marino static inline T *VEC_OP (T,A,safe_insert) \ 892*e4b17023SJohn Marino (VEC(T,A) **vec_, unsigned ix_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \ 893*e4b17023SJohn Marino { \ 894*e4b17023SJohn Marino VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \ 895*e4b17023SJohn Marino \ 896*e4b17023SJohn Marino return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \ 897*e4b17023SJohn Marino VEC_CHECK_PASS); \ 898*e4b17023SJohn Marino } 899*e4b17023SJohn Marino 900*e4b17023SJohn Marino /* Vector of object. */ 901*e4b17023SJohn Marino #define DEF_VEC_O(T) \ 902*e4b17023SJohn Marino VEC_T_GTY(T,base); \ 903*e4b17023SJohn Marino VEC_TA(T,base,none); \ 904*e4b17023SJohn Marino DEF_VEC_FUNC_O(T) \ 905*e4b17023SJohn Marino struct vec_swallow_trailing_semi 906*e4b17023SJohn Marino #define DEF_VEC_ALLOC_O(T,A) \ 907*e4b17023SJohn Marino VEC_TA(T,base,A); \ 908*e4b17023SJohn Marino DEF_VEC_ALLOC_FUNC_O(T,A) \ 909*e4b17023SJohn Marino DEF_VEC_NONALLOC_FUNCS_O(T,A) \ 910*e4b17023SJohn Marino struct vec_swallow_trailing_semi 911*e4b17023SJohn Marino 912*e4b17023SJohn Marino #define DEF_VEC_FUNC_O(T) \ 913*e4b17023SJohn Marino static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \ 914*e4b17023SJohn Marino { \ 915*e4b17023SJohn Marino return vec_ ? vec_->prefix.num : 0; \ 916*e4b17023SJohn Marino } \ 917*e4b17023SJohn Marino \ 918*e4b17023SJohn Marino static inline T *VEC_OP (T,base,last) (VEC(T,base) *vec_ VEC_CHECK_DECL) \ 919*e4b17023SJohn Marino { \ 920*e4b17023SJohn Marino VEC_ASSERT (vec_ && vec_->prefix.num, "last", T, base); \ 921*e4b17023SJohn Marino \ 922*e4b17023SJohn Marino return &vec_->vec[vec_->prefix.num - 1]; \ 923*e4b17023SJohn Marino } \ 924*e4b17023SJohn Marino \ 925*e4b17023SJohn Marino static inline T *VEC_OP (T,base,index) \ 926*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \ 927*e4b17023SJohn Marino { \ 928*e4b17023SJohn Marino VEC_ASSERT (vec_ && ix_ < vec_->prefix.num, "index", T, base); \ 929*e4b17023SJohn Marino \ 930*e4b17023SJohn Marino return &vec_->vec[ix_]; \ 931*e4b17023SJohn Marino } \ 932*e4b17023SJohn Marino \ 933*e4b17023SJohn Marino static inline int VEC_OP (T,base,iterate) \ 934*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_, T **ptr) \ 935*e4b17023SJohn Marino { \ 936*e4b17023SJohn Marino if (vec_ && ix_ < vec_->prefix.num) \ 937*e4b17023SJohn Marino { \ 938*e4b17023SJohn Marino *ptr = &vec_->vec[ix_]; \ 939*e4b17023SJohn Marino return 1; \ 940*e4b17023SJohn Marino } \ 941*e4b17023SJohn Marino else \ 942*e4b17023SJohn Marino { \ 943*e4b17023SJohn Marino *ptr = 0; \ 944*e4b17023SJohn Marino return 0; \ 945*e4b17023SJohn Marino } \ 946*e4b17023SJohn Marino } \ 947*e4b17023SJohn Marino \ 948*e4b17023SJohn Marino static inline size_t VEC_OP (T,base,embedded_size) \ 949*e4b17023SJohn Marino (int alloc_) \ 950*e4b17023SJohn Marino { \ 951*e4b17023SJohn Marino return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \ 952*e4b17023SJohn Marino } \ 953*e4b17023SJohn Marino \ 954*e4b17023SJohn Marino static inline void VEC_OP (T,base,embedded_init) \ 955*e4b17023SJohn Marino (VEC(T,base) *vec_, int alloc_) \ 956*e4b17023SJohn Marino { \ 957*e4b17023SJohn Marino vec_->prefix.num = 0; \ 958*e4b17023SJohn Marino vec_->prefix.alloc = alloc_; \ 959*e4b17023SJohn Marino } \ 960*e4b17023SJohn Marino \ 961*e4b17023SJohn Marino static inline int VEC_OP (T,base,space) \ 962*e4b17023SJohn Marino (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL) \ 963*e4b17023SJohn Marino { \ 964*e4b17023SJohn Marino VEC_ASSERT (alloc_ >= 0, "space", T, base); \ 965*e4b17023SJohn Marino return vec_ ? vec_->prefix.alloc - vec_->prefix.num >= (unsigned)alloc_ : !alloc_; \ 966*e4b17023SJohn Marino } \ 967*e4b17023SJohn Marino \ 968*e4b17023SJohn Marino static inline void VEC_OP(T,base,splice) \ 969*e4b17023SJohn Marino (VEC(T,base) *dst_, VEC(T,base) *src_ VEC_CHECK_DECL) \ 970*e4b17023SJohn Marino { \ 971*e4b17023SJohn Marino if (src_) \ 972*e4b17023SJohn Marino { \ 973*e4b17023SJohn Marino unsigned len_ = src_->prefix.num; \ 974*e4b17023SJohn Marino VEC_ASSERT (dst_->prefix.num + len_ <= dst_->prefix.alloc, "splice", T, base); \ 975*e4b17023SJohn Marino \ 976*e4b17023SJohn Marino memcpy (&dst_->vec[dst_->prefix.num], &src_->vec[0], len_ * sizeof (T)); \ 977*e4b17023SJohn Marino dst_->prefix.num += len_; \ 978*e4b17023SJohn Marino } \ 979*e4b17023SJohn Marino } \ 980*e4b17023SJohn Marino \ 981*e4b17023SJohn Marino static inline T *VEC_OP (T,base,quick_push) \ 982*e4b17023SJohn Marino (VEC(T,base) *vec_, const T *obj_ VEC_CHECK_DECL) \ 983*e4b17023SJohn Marino { \ 984*e4b17023SJohn Marino T *slot_; \ 985*e4b17023SJohn Marino \ 986*e4b17023SJohn Marino VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base); \ 987*e4b17023SJohn Marino slot_ = &vec_->vec[vec_->prefix.num++]; \ 988*e4b17023SJohn Marino if (obj_) \ 989*e4b17023SJohn Marino *slot_ = *obj_; \ 990*e4b17023SJohn Marino \ 991*e4b17023SJohn Marino return slot_; \ 992*e4b17023SJohn Marino } \ 993*e4b17023SJohn Marino \ 994*e4b17023SJohn Marino static inline void VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \ 995*e4b17023SJohn Marino { \ 996*e4b17023SJohn Marino VEC_ASSERT (vec_->prefix.num, "pop", T, base); \ 997*e4b17023SJohn Marino --vec_->prefix.num; \ 998*e4b17023SJohn Marino } \ 999*e4b17023SJohn Marino \ 1000*e4b17023SJohn Marino static inline void VEC_OP (T,base,truncate) \ 1001*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL) \ 1002*e4b17023SJohn Marino { \ 1003*e4b17023SJohn Marino VEC_ASSERT (vec_ ? vec_->prefix.num >= size_ : !size_, "truncate", T, base); \ 1004*e4b17023SJohn Marino if (vec_) \ 1005*e4b17023SJohn Marino vec_->prefix.num = size_; \ 1006*e4b17023SJohn Marino } \ 1007*e4b17023SJohn Marino \ 1008*e4b17023SJohn Marino static inline T *VEC_OP (T,base,replace) \ 1009*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \ 1010*e4b17023SJohn Marino { \ 1011*e4b17023SJohn Marino T *slot_; \ 1012*e4b17023SJohn Marino \ 1013*e4b17023SJohn Marino VEC_ASSERT (ix_ < vec_->prefix.num, "replace", T, base); \ 1014*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 1015*e4b17023SJohn Marino if (obj_) \ 1016*e4b17023SJohn Marino *slot_ = *obj_; \ 1017*e4b17023SJohn Marino \ 1018*e4b17023SJohn Marino return slot_; \ 1019*e4b17023SJohn Marino } \ 1020*e4b17023SJohn Marino \ 1021*e4b17023SJohn Marino static inline T *VEC_OP (T,base,quick_insert) \ 1022*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \ 1023*e4b17023SJohn Marino { \ 1024*e4b17023SJohn Marino T *slot_; \ 1025*e4b17023SJohn Marino \ 1026*e4b17023SJohn Marino VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "insert", T, base); \ 1027*e4b17023SJohn Marino VEC_ASSERT (ix_ <= vec_->prefix.num, "insert", T, base); \ 1028*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 1029*e4b17023SJohn Marino memmove (slot_ + 1, slot_, (vec_->prefix.num++ - ix_) * sizeof (T)); \ 1030*e4b17023SJohn Marino if (obj_) \ 1031*e4b17023SJohn Marino *slot_ = *obj_; \ 1032*e4b17023SJohn Marino \ 1033*e4b17023SJohn Marino return slot_; \ 1034*e4b17023SJohn Marino } \ 1035*e4b17023SJohn Marino \ 1036*e4b17023SJohn Marino static inline void VEC_OP (T,base,ordered_remove) \ 1037*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \ 1038*e4b17023SJohn Marino { \ 1039*e4b17023SJohn Marino T *slot_; \ 1040*e4b17023SJohn Marino \ 1041*e4b17023SJohn Marino VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base); \ 1042*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 1043*e4b17023SJohn Marino memmove (slot_, slot_ + 1, (--vec_->prefix.num - ix_) * sizeof (T)); \ 1044*e4b17023SJohn Marino } \ 1045*e4b17023SJohn Marino \ 1046*e4b17023SJohn Marino static inline void VEC_OP (T,base,unordered_remove) \ 1047*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \ 1048*e4b17023SJohn Marino { \ 1049*e4b17023SJohn Marino VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base); \ 1050*e4b17023SJohn Marino vec_->vec[ix_] = vec_->vec[--vec_->prefix.num]; \ 1051*e4b17023SJohn Marino } \ 1052*e4b17023SJohn Marino \ 1053*e4b17023SJohn Marino static inline void VEC_OP (T,base,block_remove) \ 1054*e4b17023SJohn Marino (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL) \ 1055*e4b17023SJohn Marino { \ 1056*e4b17023SJohn Marino T *slot_; \ 1057*e4b17023SJohn Marino \ 1058*e4b17023SJohn Marino VEC_ASSERT (ix_ + len_ <= vec_->prefix.num, "block_remove", T, base); \ 1059*e4b17023SJohn Marino slot_ = &vec_->vec[ix_]; \ 1060*e4b17023SJohn Marino vec_->prefix.num -= len_; \ 1061*e4b17023SJohn Marino memmove (slot_, slot_ + len_, (vec_->prefix.num - ix_) * sizeof (T)); \ 1062*e4b17023SJohn Marino } \ 1063*e4b17023SJohn Marino \ 1064*e4b17023SJohn Marino static inline T *VEC_OP (T,base,address) \ 1065*e4b17023SJohn Marino (VEC(T,base) *vec_) \ 1066*e4b17023SJohn Marino { \ 1067*e4b17023SJohn Marino return vec_ ? vec_->vec : 0; \ 1068*e4b17023SJohn Marino } \ 1069*e4b17023SJohn Marino \ 1070*e4b17023SJohn Marino static inline unsigned VEC_OP (T,base,lower_bound) \ 1071*e4b17023SJohn Marino (VEC(T,base) *vec_, const T *obj_, \ 1072*e4b17023SJohn Marino bool (*lessthan_)(const T *, const T *) VEC_CHECK_DECL) \ 1073*e4b17023SJohn Marino { \ 1074*e4b17023SJohn Marino unsigned int len_ = VEC_OP (T, base, length) (vec_); \ 1075*e4b17023SJohn Marino unsigned int half_, middle_; \ 1076*e4b17023SJohn Marino unsigned int first_ = 0; \ 1077*e4b17023SJohn Marino while (len_ > 0) \ 1078*e4b17023SJohn Marino { \ 1079*e4b17023SJohn Marino T *middle_elem_; \ 1080*e4b17023SJohn Marino half_ = len_ >> 1; \ 1081*e4b17023SJohn Marino middle_ = first_; \ 1082*e4b17023SJohn Marino middle_ += half_; \ 1083*e4b17023SJohn Marino middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \ 1084*e4b17023SJohn Marino if (lessthan_ (middle_elem_, obj_)) \ 1085*e4b17023SJohn Marino { \ 1086*e4b17023SJohn Marino first_ = middle_; \ 1087*e4b17023SJohn Marino ++first_; \ 1088*e4b17023SJohn Marino len_ = len_ - half_ - 1; \ 1089*e4b17023SJohn Marino } \ 1090*e4b17023SJohn Marino else \ 1091*e4b17023SJohn Marino len_ = half_; \ 1092*e4b17023SJohn Marino } \ 1093*e4b17023SJohn Marino return first_; \ 1094*e4b17023SJohn Marino } 1095*e4b17023SJohn Marino 1096*e4b17023SJohn Marino #define DEF_VEC_ALLOC_FUNC_O(T,A) \ 1097*e4b17023SJohn Marino static inline VEC(T,A) *VEC_OP (T,A,alloc) \ 1098*e4b17023SJohn Marino (int alloc_ MEM_STAT_DECL) \ 1099*e4b17023SJohn Marino { \ 1100*e4b17023SJohn Marino return (VEC(T,A) *) vec_##A##_o_reserve_exact (NULL, alloc_, \ 1101*e4b17023SJohn Marino offsetof (VEC(T,A),base.vec), \ 1102*e4b17023SJohn Marino sizeof (T) \ 1103*e4b17023SJohn Marino PASS_MEM_STAT); \ 1104*e4b17023SJohn Marino } 1105*e4b17023SJohn Marino 1106*e4b17023SJohn Marino #define DEF_VEC_NONALLOC_FUNCS_O(T,A) \ 1107*e4b17023SJohn Marino static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \ 1108*e4b17023SJohn Marino { \ 1109*e4b17023SJohn Marino size_t len_ = vec_ ? vec_->prefix.num : 0; \ 1110*e4b17023SJohn Marino VEC (T,A) *new_vec_ = NULL; \ 1111*e4b17023SJohn Marino \ 1112*e4b17023SJohn Marino if (len_) \ 1113*e4b17023SJohn Marino { \ 1114*e4b17023SJohn Marino new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \ 1115*e4b17023SJohn Marino (NULL, len_, \ 1116*e4b17023SJohn Marino offsetof (VEC(T,A),base.vec), sizeof (T) \ 1117*e4b17023SJohn Marino PASS_MEM_STAT)); \ 1118*e4b17023SJohn Marino \ 1119*e4b17023SJohn Marino new_vec_->base.prefix.num = len_; \ 1120*e4b17023SJohn Marino memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \ 1121*e4b17023SJohn Marino } \ 1122*e4b17023SJohn Marino return new_vec_; \ 1123*e4b17023SJohn Marino } \ 1124*e4b17023SJohn Marino \ 1125*e4b17023SJohn Marino static inline void VEC_OP (T,A,free) \ 1126*e4b17023SJohn Marino (VEC(T,A) **vec_) \ 1127*e4b17023SJohn Marino { \ 1128*e4b17023SJohn Marino if (*vec_) \ 1129*e4b17023SJohn Marino vec_##A##_free (*vec_); \ 1130*e4b17023SJohn Marino *vec_ = NULL; \ 1131*e4b17023SJohn Marino } \ 1132*e4b17023SJohn Marino \ 1133*e4b17023SJohn Marino static inline int VEC_OP (T,A,reserve) \ 1134*e4b17023SJohn Marino (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1135*e4b17023SJohn Marino { \ 1136*e4b17023SJohn Marino int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \ 1137*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1138*e4b17023SJohn Marino \ 1139*e4b17023SJohn Marino if (extend) \ 1140*e4b17023SJohn Marino *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_, \ 1141*e4b17023SJohn Marino offsetof (VEC(T,A),base.vec),\ 1142*e4b17023SJohn Marino sizeof (T) \ 1143*e4b17023SJohn Marino PASS_MEM_STAT); \ 1144*e4b17023SJohn Marino \ 1145*e4b17023SJohn Marino return extend; \ 1146*e4b17023SJohn Marino } \ 1147*e4b17023SJohn Marino \ 1148*e4b17023SJohn Marino static inline int VEC_OP (T,A,reserve_exact) \ 1149*e4b17023SJohn Marino (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1150*e4b17023SJohn Marino { \ 1151*e4b17023SJohn Marino int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \ 1152*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1153*e4b17023SJohn Marino \ 1154*e4b17023SJohn Marino if (extend) \ 1155*e4b17023SJohn Marino *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \ 1156*e4b17023SJohn Marino (*vec_, alloc_, \ 1157*e4b17023SJohn Marino offsetof (VEC(T,A),base.vec), \ 1158*e4b17023SJohn Marino sizeof (T) PASS_MEM_STAT); \ 1159*e4b17023SJohn Marino \ 1160*e4b17023SJohn Marino return extend; \ 1161*e4b17023SJohn Marino } \ 1162*e4b17023SJohn Marino \ 1163*e4b17023SJohn Marino static inline void VEC_OP (T,A,safe_grow) \ 1164*e4b17023SJohn Marino (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1165*e4b17023SJohn Marino { \ 1166*e4b17023SJohn Marino VEC_ASSERT (size_ >= 0 \ 1167*e4b17023SJohn Marino && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \ 1168*e4b17023SJohn Marino "grow", T, A); \ 1169*e4b17023SJohn Marino VEC_OP (T,A,reserve_exact) (vec_, \ 1170*e4b17023SJohn Marino size_ - (int)(*vec_ ? VEC_BASE(*vec_)->prefix.num : 0) \ 1171*e4b17023SJohn Marino VEC_CHECK_PASS PASS_MEM_STAT); \ 1172*e4b17023SJohn Marino VEC_BASE (*vec_)->prefix.num = size_; \ 1173*e4b17023SJohn Marino } \ 1174*e4b17023SJohn Marino \ 1175*e4b17023SJohn Marino static inline void VEC_OP (T,A,safe_grow_cleared) \ 1176*e4b17023SJohn Marino (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1177*e4b17023SJohn Marino { \ 1178*e4b17023SJohn Marino int oldsize = VEC_OP(T,base,length) VEC_BASE(*vec_); \ 1179*e4b17023SJohn Marino VEC_OP (T,A,safe_grow) (vec_, size_ VEC_CHECK_PASS PASS_MEM_STAT); \ 1180*e4b17023SJohn Marino memset (&(VEC_OP (T,base,address) VEC_BASE(*vec_))[oldsize], 0, \ 1181*e4b17023SJohn Marino sizeof (T) * (size_ - oldsize)); \ 1182*e4b17023SJohn Marino } \ 1183*e4b17023SJohn Marino \ 1184*e4b17023SJohn Marino static inline void VEC_OP(T,A,safe_splice) \ 1185*e4b17023SJohn Marino (VEC(T,A) **dst_, VEC(T,base) *src_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1186*e4b17023SJohn Marino { \ 1187*e4b17023SJohn Marino if (src_) \ 1188*e4b17023SJohn Marino { \ 1189*e4b17023SJohn Marino VEC_OP (T,A,reserve_exact) (dst_, src_->prefix.num \ 1190*e4b17023SJohn Marino VEC_CHECK_PASS MEM_STAT_INFO); \ 1191*e4b17023SJohn Marino \ 1192*e4b17023SJohn Marino VEC_OP (T,base,splice) (VEC_BASE (*dst_), src_ \ 1193*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1194*e4b17023SJohn Marino } \ 1195*e4b17023SJohn Marino } \ 1196*e4b17023SJohn Marino \ 1197*e4b17023SJohn Marino static inline T *VEC_OP (T,A,safe_push) \ 1198*e4b17023SJohn Marino (VEC(T,A) **vec_, const T *obj_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1199*e4b17023SJohn Marino { \ 1200*e4b17023SJohn Marino VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \ 1201*e4b17023SJohn Marino \ 1202*e4b17023SJohn Marino return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \ 1203*e4b17023SJohn Marino } \ 1204*e4b17023SJohn Marino \ 1205*e4b17023SJohn Marino static inline T *VEC_OP (T,A,safe_insert) \ 1206*e4b17023SJohn Marino (VEC(T,A) **vec_, unsigned ix_, const T *obj_ \ 1207*e4b17023SJohn Marino VEC_CHECK_DECL MEM_STAT_DECL) \ 1208*e4b17023SJohn Marino { \ 1209*e4b17023SJohn Marino VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \ 1210*e4b17023SJohn Marino \ 1211*e4b17023SJohn Marino return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \ 1212*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1213*e4b17023SJohn Marino } 1214*e4b17023SJohn Marino 1215*e4b17023SJohn Marino #define DEF_VEC_ALLOC_FUNC_I(T,A) \ 1216*e4b17023SJohn Marino static inline VEC(T,A) *VEC_OP (T,A,alloc) \ 1217*e4b17023SJohn Marino (int alloc_ MEM_STAT_DECL) \ 1218*e4b17023SJohn Marino { \ 1219*e4b17023SJohn Marino return (VEC(T,A) *) vec_##A##_o_reserve_exact \ 1220*e4b17023SJohn Marino (NULL, alloc_, offsetof (VEC(T,A),base.vec), \ 1221*e4b17023SJohn Marino sizeof (T) PASS_MEM_STAT); \ 1222*e4b17023SJohn Marino } 1223*e4b17023SJohn Marino 1224*e4b17023SJohn Marino #define DEF_VEC_NONALLOC_FUNCS_I(T,A) \ 1225*e4b17023SJohn Marino static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \ 1226*e4b17023SJohn Marino { \ 1227*e4b17023SJohn Marino size_t len_ = vec_ ? vec_->prefix.num : 0; \ 1228*e4b17023SJohn Marino VEC (T,A) *new_vec_ = NULL; \ 1229*e4b17023SJohn Marino \ 1230*e4b17023SJohn Marino if (len_) \ 1231*e4b17023SJohn Marino { \ 1232*e4b17023SJohn Marino new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \ 1233*e4b17023SJohn Marino (NULL, len_, \ 1234*e4b17023SJohn Marino offsetof (VEC(T,A),base.vec), sizeof (T) \ 1235*e4b17023SJohn Marino PASS_MEM_STAT)); \ 1236*e4b17023SJohn Marino \ 1237*e4b17023SJohn Marino new_vec_->base.prefix.num = len_; \ 1238*e4b17023SJohn Marino memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \ 1239*e4b17023SJohn Marino } \ 1240*e4b17023SJohn Marino return new_vec_; \ 1241*e4b17023SJohn Marino } \ 1242*e4b17023SJohn Marino \ 1243*e4b17023SJohn Marino static inline void VEC_OP (T,A,free) \ 1244*e4b17023SJohn Marino (VEC(T,A) **vec_) \ 1245*e4b17023SJohn Marino { \ 1246*e4b17023SJohn Marino if (*vec_) \ 1247*e4b17023SJohn Marino vec_##A##_free (*vec_); \ 1248*e4b17023SJohn Marino *vec_ = NULL; \ 1249*e4b17023SJohn Marino } \ 1250*e4b17023SJohn Marino \ 1251*e4b17023SJohn Marino static inline int VEC_OP (T,A,reserve) \ 1252*e4b17023SJohn Marino (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1253*e4b17023SJohn Marino { \ 1254*e4b17023SJohn Marino int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \ 1255*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1256*e4b17023SJohn Marino \ 1257*e4b17023SJohn Marino if (extend) \ 1258*e4b17023SJohn Marino *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_, \ 1259*e4b17023SJohn Marino offsetof (VEC(T,A),base.vec),\ 1260*e4b17023SJohn Marino sizeof (T) \ 1261*e4b17023SJohn Marino PASS_MEM_STAT); \ 1262*e4b17023SJohn Marino \ 1263*e4b17023SJohn Marino return extend; \ 1264*e4b17023SJohn Marino } \ 1265*e4b17023SJohn Marino \ 1266*e4b17023SJohn Marino static inline int VEC_OP (T,A,reserve_exact) \ 1267*e4b17023SJohn Marino (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1268*e4b17023SJohn Marino { \ 1269*e4b17023SJohn Marino int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \ 1270*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1271*e4b17023SJohn Marino \ 1272*e4b17023SJohn Marino if (extend) \ 1273*e4b17023SJohn Marino *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \ 1274*e4b17023SJohn Marino (*vec_, alloc_, offsetof (VEC(T,A),base.vec), \ 1275*e4b17023SJohn Marino sizeof (T) PASS_MEM_STAT); \ 1276*e4b17023SJohn Marino \ 1277*e4b17023SJohn Marino return extend; \ 1278*e4b17023SJohn Marino } \ 1279*e4b17023SJohn Marino \ 1280*e4b17023SJohn Marino static inline void VEC_OP (T,A,safe_grow) \ 1281*e4b17023SJohn Marino (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1282*e4b17023SJohn Marino { \ 1283*e4b17023SJohn Marino VEC_ASSERT (size_ >= 0 \ 1284*e4b17023SJohn Marino && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \ 1285*e4b17023SJohn Marino "grow", T, A); \ 1286*e4b17023SJohn Marino VEC_OP (T,A,reserve_exact) (vec_, \ 1287*e4b17023SJohn Marino size_ - (int)(*vec_ ? VEC_BASE(*vec_)->prefix.num : 0) \ 1288*e4b17023SJohn Marino VEC_CHECK_PASS PASS_MEM_STAT); \ 1289*e4b17023SJohn Marino VEC_BASE (*vec_)->prefix.num = size_; \ 1290*e4b17023SJohn Marino } \ 1291*e4b17023SJohn Marino \ 1292*e4b17023SJohn Marino static inline void VEC_OP (T,A,safe_grow_cleared) \ 1293*e4b17023SJohn Marino (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1294*e4b17023SJohn Marino { \ 1295*e4b17023SJohn Marino int oldsize = VEC_OP(T,base,length) VEC_BASE(*vec_); \ 1296*e4b17023SJohn Marino VEC_OP (T,A,safe_grow) (vec_, size_ VEC_CHECK_PASS PASS_MEM_STAT); \ 1297*e4b17023SJohn Marino memset (&(VEC_OP (T,base,address) VEC_BASE(*vec_))[oldsize], 0, \ 1298*e4b17023SJohn Marino sizeof (T) * (size_ - oldsize)); \ 1299*e4b17023SJohn Marino } \ 1300*e4b17023SJohn Marino \ 1301*e4b17023SJohn Marino static inline void VEC_OP(T,A,safe_splice) \ 1302*e4b17023SJohn Marino (VEC(T,A) **dst_, VEC(T,base) *src_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1303*e4b17023SJohn Marino { \ 1304*e4b17023SJohn Marino if (src_) \ 1305*e4b17023SJohn Marino { \ 1306*e4b17023SJohn Marino VEC_OP (T,A,reserve_exact) (dst_, src_->prefix.num \ 1307*e4b17023SJohn Marino VEC_CHECK_PASS MEM_STAT_INFO); \ 1308*e4b17023SJohn Marino \ 1309*e4b17023SJohn Marino VEC_OP (T,base,splice) (VEC_BASE (*dst_), src_ \ 1310*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1311*e4b17023SJohn Marino } \ 1312*e4b17023SJohn Marino } \ 1313*e4b17023SJohn Marino \ 1314*e4b17023SJohn Marino static inline T *VEC_OP (T,A,safe_push) \ 1315*e4b17023SJohn Marino (VEC(T,A) **vec_, const T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \ 1316*e4b17023SJohn Marino { \ 1317*e4b17023SJohn Marino VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \ 1318*e4b17023SJohn Marino \ 1319*e4b17023SJohn Marino return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \ 1320*e4b17023SJohn Marino } \ 1321*e4b17023SJohn Marino \ 1322*e4b17023SJohn Marino static inline T *VEC_OP (T,A,safe_insert) \ 1323*e4b17023SJohn Marino (VEC(T,A) **vec_, unsigned ix_, const T obj_ \ 1324*e4b17023SJohn Marino VEC_CHECK_DECL MEM_STAT_DECL) \ 1325*e4b17023SJohn Marino { \ 1326*e4b17023SJohn Marino VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \ 1327*e4b17023SJohn Marino \ 1328*e4b17023SJohn Marino return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \ 1329*e4b17023SJohn Marino VEC_CHECK_PASS); \ 1330*e4b17023SJohn Marino } 1331*e4b17023SJohn Marino 1332*e4b17023SJohn Marino /* We support a vector which starts out with space on the stack and 1333*e4b17023SJohn Marino switches to heap space when forced to reallocate. This works a 1334*e4b17023SJohn Marino little differently. Instead of DEF_VEC_ALLOC_P(TYPE, heap|gc), use 1335*e4b17023SJohn Marino DEF_VEC_ALLOC_P_STACK(TYPE). This uses alloca to get the initial 1336*e4b17023SJohn Marino space; because alloca can not be usefully called in an inline 1337*e4b17023SJohn Marino function, and because a macro can not define a macro, you must then 1338*e4b17023SJohn Marino write a #define for each type: 1339*e4b17023SJohn Marino 1340*e4b17023SJohn Marino #define VEC_{TYPE}_stack_alloc(alloc) \ 1341*e4b17023SJohn Marino VEC_stack_alloc({TYPE}, alloc) 1342*e4b17023SJohn Marino 1343*e4b17023SJohn Marino This is really a hack and perhaps can be made better. Note that 1344*e4b17023SJohn Marino this macro will wind up evaluating the ALLOC parameter twice. 1345*e4b17023SJohn Marino 1346*e4b17023SJohn Marino Only the initial allocation will be made using alloca, so pass a 1347*e4b17023SJohn Marino reasonable estimate that doesn't use too much stack space; don't 1348*e4b17023SJohn Marino pass zero. Don't return a VEC(TYPE,stack) vector from the function 1349*e4b17023SJohn Marino which allocated it. */ 1350*e4b17023SJohn Marino 1351*e4b17023SJohn Marino extern void *vec_stack_p_reserve (void *, int MEM_STAT_DECL); 1352*e4b17023SJohn Marino extern void *vec_stack_p_reserve_exact (void *, int MEM_STAT_DECL); 1353*e4b17023SJohn Marino extern void *vec_stack_p_reserve_exact_1 (int, void *); 1354*e4b17023SJohn Marino extern void *vec_stack_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL); 1355*e4b17023SJohn Marino extern void *vec_stack_o_reserve_exact (void *, int, size_t, size_t 1356*e4b17023SJohn Marino MEM_STAT_DECL); 1357*e4b17023SJohn Marino extern void vec_stack_free (void *); 1358*e4b17023SJohn Marino 1359*e4b17023SJohn Marino #ifdef GATHER_STATISTICS 1360*e4b17023SJohn Marino #define VEC_stack_alloc(T,alloc,name,line,function) \ 1361*e4b17023SJohn Marino (VEC_OP (T,stack,alloc1) \ 1362*e4b17023SJohn Marino (alloc, XALLOCAVAR (VEC(T,stack), VEC_embedded_size (T, alloc)))) 1363*e4b17023SJohn Marino #else 1364*e4b17023SJohn Marino #define VEC_stack_alloc(T,alloc) \ 1365*e4b17023SJohn Marino (VEC_OP (T,stack,alloc1) \ 1366*e4b17023SJohn Marino (alloc, XALLOCAVAR (VEC(T,stack), VEC_embedded_size (T, alloc)))) 1367*e4b17023SJohn Marino #endif 1368*e4b17023SJohn Marino 1369*e4b17023SJohn Marino #define DEF_VEC_ALLOC_P_STACK(T) \ 1370*e4b17023SJohn Marino VEC_TA(T,base,stack); \ 1371*e4b17023SJohn Marino DEF_VEC_ALLOC_FUNC_P_STACK(T) \ 1372*e4b17023SJohn Marino DEF_VEC_NONALLOC_FUNCS_P(T,stack) \ 1373*e4b17023SJohn Marino struct vec_swallow_trailing_semi 1374*e4b17023SJohn Marino 1375*e4b17023SJohn Marino #define DEF_VEC_ALLOC_FUNC_P_STACK(T) \ 1376*e4b17023SJohn Marino static inline VEC(T,stack) *VEC_OP (T,stack,alloc1) \ 1377*e4b17023SJohn Marino (int alloc_, VEC(T,stack)* space) \ 1378*e4b17023SJohn Marino { \ 1379*e4b17023SJohn Marino return (VEC(T,stack) *) vec_stack_p_reserve_exact_1 (alloc_, space); \ 1380*e4b17023SJohn Marino } 1381*e4b17023SJohn Marino 1382*e4b17023SJohn Marino #define DEF_VEC_ALLOC_O_STACK(T) \ 1383*e4b17023SJohn Marino VEC_TA(T,base,stack); \ 1384*e4b17023SJohn Marino DEF_VEC_ALLOC_FUNC_O_STACK(T) \ 1385*e4b17023SJohn Marino DEF_VEC_NONALLOC_FUNCS_O(T,stack) \ 1386*e4b17023SJohn Marino struct vec_swallow_trailing_semi 1387*e4b17023SJohn Marino 1388*e4b17023SJohn Marino #define DEF_VEC_ALLOC_FUNC_O_STACK(T) \ 1389*e4b17023SJohn Marino static inline VEC(T,stack) *VEC_OP (T,stack,alloc1) \ 1390*e4b17023SJohn Marino (int alloc_, VEC(T,stack)* space) \ 1391*e4b17023SJohn Marino { \ 1392*e4b17023SJohn Marino return (VEC(T,stack) *) vec_stack_p_reserve_exact_1 (alloc_, space); \ 1393*e4b17023SJohn Marino } 1394*e4b17023SJohn Marino 1395*e4b17023SJohn Marino #define DEF_VEC_ALLOC_I_STACK(T) \ 1396*e4b17023SJohn Marino VEC_TA(T,base,stack); \ 1397*e4b17023SJohn Marino DEF_VEC_ALLOC_FUNC_I_STACK(T) \ 1398*e4b17023SJohn Marino DEF_VEC_NONALLOC_FUNCS_I(T,stack) \ 1399*e4b17023SJohn Marino struct vec_swallow_trailing_semi 1400*e4b17023SJohn Marino 1401*e4b17023SJohn Marino #define DEF_VEC_ALLOC_FUNC_I_STACK(T) \ 1402*e4b17023SJohn Marino static inline VEC(T,stack) *VEC_OP (T,stack,alloc1) \ 1403*e4b17023SJohn Marino (int alloc_, VEC(T,stack)* space) \ 1404*e4b17023SJohn Marino { \ 1405*e4b17023SJohn Marino return (VEC(T,stack) *) vec_stack_p_reserve_exact_1 (alloc_, space); \ 1406*e4b17023SJohn Marino } 1407*e4b17023SJohn Marino 1408*e4b17023SJohn Marino #endif /* GCC_VEC_H */ 1409