11debfc3dSmrg /* Vector API for GNU compiler.
2*8feb0f0bSmrg Copyright (C) 2004-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Nathan Sidwell <nathan@codesourcery.com>
41debfc3dSmrg Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
51debfc3dSmrg
61debfc3dSmrg This file is part of GCC.
71debfc3dSmrg
81debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
91debfc3dSmrg the terms of the GNU General Public License as published by the Free
101debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
111debfc3dSmrg version.
121debfc3dSmrg
131debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
141debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
151debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
161debfc3dSmrg for more details.
171debfc3dSmrg
181debfc3dSmrg You should have received a copy of the GNU General Public License
191debfc3dSmrg along with GCC; see the file COPYING3. If not see
201debfc3dSmrg <http://www.gnu.org/licenses/>. */
211debfc3dSmrg
221debfc3dSmrg #ifndef GCC_VEC_H
231debfc3dSmrg #define GCC_VEC_H
241debfc3dSmrg
251debfc3dSmrg /* Some gen* file have no ggc support as the header file gtype-desc.h is
261debfc3dSmrg missing. Provide these definitions in case ggc.h has not been included.
271debfc3dSmrg This is not a problem because any code that runs before gengtype is built
281debfc3dSmrg will never need to use GC vectors.*/
291debfc3dSmrg
301debfc3dSmrg extern void ggc_free (void *);
311debfc3dSmrg extern size_t ggc_round_alloc_size (size_t requested_size);
321debfc3dSmrg extern void *ggc_realloc (void *, size_t MEM_STAT_DECL);
331debfc3dSmrg
341debfc3dSmrg /* Templated vector type and associated interfaces.
351debfc3dSmrg
361debfc3dSmrg The interface functions are typesafe and use inline functions,
371debfc3dSmrg sometimes backed by out-of-line generic functions. The vectors are
381debfc3dSmrg designed to interoperate with the GTY machinery.
391debfc3dSmrg
401debfc3dSmrg There are both 'index' and 'iterate' accessors. The index accessor
411debfc3dSmrg is implemented by operator[]. The iterator returns a boolean
421debfc3dSmrg iteration condition and updates the iteration variable passed by
431debfc3dSmrg reference. Because the iterator will be inlined, the address-of
441debfc3dSmrg can be optimized away.
451debfc3dSmrg
461debfc3dSmrg Each operation that increases the number of active elements is
471debfc3dSmrg available in 'quick' and 'safe' variants. The former presumes that
481debfc3dSmrg there is sufficient allocated space for the operation to succeed
491debfc3dSmrg (it dies if there is not). The latter will reallocate the
501debfc3dSmrg vector, if needed. Reallocation causes an exponential increase in
511debfc3dSmrg vector size. If you know you will be adding N elements, it would
521debfc3dSmrg be more efficient to use the reserve operation before adding the
531debfc3dSmrg elements with the 'quick' operation. This will ensure there are at
541debfc3dSmrg least as many elements as you ask for, it will exponentially
551debfc3dSmrg increase if there are too few spare slots. If you want reserve a
561debfc3dSmrg specific number of slots, but do not want the exponential increase
571debfc3dSmrg (for instance, you know this is the last allocation), use the
581debfc3dSmrg reserve_exact operation. You can also create a vector of a
591debfc3dSmrg specific size from the get go.
601debfc3dSmrg
611debfc3dSmrg You should prefer the push and pop operations, as they append and
621debfc3dSmrg remove from the end of the vector. If you need to remove several
631debfc3dSmrg items in one go, use the truncate operation. The insert and remove
641debfc3dSmrg operations allow you to change elements in the middle of the
651debfc3dSmrg vector. There are two remove operations, one which preserves the
661debfc3dSmrg element ordering 'ordered_remove', and one which does not
671debfc3dSmrg 'unordered_remove'. The latter function copies the end element
681debfc3dSmrg into the removed slot, rather than invoke a memmove operation. The
691debfc3dSmrg 'lower_bound' function will determine where to place an item in the
701debfc3dSmrg array using insert that will maintain sorted order.
711debfc3dSmrg
721debfc3dSmrg Vectors are template types with three arguments: the type of the
731debfc3dSmrg elements in the vector, the allocation strategy, and the physical
741debfc3dSmrg layout to use
751debfc3dSmrg
761debfc3dSmrg Four allocation strategies are supported:
771debfc3dSmrg
781debfc3dSmrg - Heap: allocation is done using malloc/free. This is the
791debfc3dSmrg default allocation strategy.
801debfc3dSmrg
811debfc3dSmrg - GC: allocation is done using ggc_alloc/ggc_free.
821debfc3dSmrg
831debfc3dSmrg - GC atomic: same as GC with the exception that the elements
841debfc3dSmrg themselves are assumed to be of an atomic type that does
851debfc3dSmrg not need to be garbage collected. This means that marking
861debfc3dSmrg routines do not need to traverse the array marking the
871debfc3dSmrg individual elements. This increases the performance of
881debfc3dSmrg GC activities.
891debfc3dSmrg
901debfc3dSmrg Two physical layouts are supported:
911debfc3dSmrg
921debfc3dSmrg - Embedded: The vector is structured using the trailing array
931debfc3dSmrg idiom. The last member of the structure is an array of size
941debfc3dSmrg 1. When the vector is initially allocated, a single memory
951debfc3dSmrg block is created to hold the vector's control data and the
961debfc3dSmrg array of elements. These vectors cannot grow without
971debfc3dSmrg reallocation (see discussion on embeddable vectors below).
981debfc3dSmrg
991debfc3dSmrg - Space efficient: The vector is structured as a pointer to an
1001debfc3dSmrg embedded vector. This is the default layout. It means that
1011debfc3dSmrg vectors occupy a single word of storage before initial
1021debfc3dSmrg allocation. Vectors are allowed to grow (the internal
1031debfc3dSmrg pointer is reallocated but the main vector instance does not
1041debfc3dSmrg need to relocate).
1051debfc3dSmrg
1061debfc3dSmrg The type, allocation and layout are specified when the vector is
1071debfc3dSmrg declared.
1081debfc3dSmrg
1091debfc3dSmrg If you need to directly manipulate a vector, then the 'address'
1101debfc3dSmrg accessor will return the address of the start of the vector. Also
1111debfc3dSmrg the 'space' predicate will tell you whether there is spare capacity
1121debfc3dSmrg in the vector. You will not normally need to use these two functions.
1131debfc3dSmrg
1141debfc3dSmrg Notes on the different layout strategies
1151debfc3dSmrg
1161debfc3dSmrg * Embeddable vectors (vec<T, A, vl_embed>)
1171debfc3dSmrg
1181debfc3dSmrg These vectors are suitable to be embedded in other data
1191debfc3dSmrg structures so that they can be pre-allocated in a contiguous
1201debfc3dSmrg memory block.
1211debfc3dSmrg
1221debfc3dSmrg Embeddable vectors are implemented using the trailing array
1231debfc3dSmrg idiom, thus they are not resizeable without changing the address
1241debfc3dSmrg of the vector object itself. This means you cannot have
1251debfc3dSmrg variables or fields of embeddable vector type -- always use a
1261debfc3dSmrg pointer to a vector. The one exception is the final field of a
1271debfc3dSmrg structure, which could be a vector type.
1281debfc3dSmrg
1291debfc3dSmrg You will have to use the embedded_size & embedded_init calls to
1301debfc3dSmrg create such objects, and they will not be resizeable (so the
1311debfc3dSmrg 'safe' allocation variants are not available).
1321debfc3dSmrg
1331debfc3dSmrg Properties of embeddable vectors:
1341debfc3dSmrg
1351debfc3dSmrg - The whole vector and control data are allocated in a single
1361debfc3dSmrg contiguous block. It uses the trailing-vector idiom, so
1371debfc3dSmrg allocation must reserve enough space for all the elements
1381debfc3dSmrg in the vector plus its control data.
1391debfc3dSmrg - The vector cannot be re-allocated.
1401debfc3dSmrg - The vector cannot grow nor shrink.
1411debfc3dSmrg - No indirections needed for access/manipulation.
1421debfc3dSmrg - It requires 2 words of storage (prior to vector allocation).
1431debfc3dSmrg
1441debfc3dSmrg
1451debfc3dSmrg * Space efficient vector (vec<T, A, vl_ptr>)
1461debfc3dSmrg
1471debfc3dSmrg These vectors can grow dynamically and are allocated together
1481debfc3dSmrg with their control data. They are suited to be included in data
1491debfc3dSmrg structures. Prior to initial allocation, they only take a single
1501debfc3dSmrg word of storage.
1511debfc3dSmrg
1521debfc3dSmrg These vectors are implemented as a pointer to embeddable vectors.
1531debfc3dSmrg The semantics allow for this pointer to be NULL to represent
1541debfc3dSmrg empty vectors. This way, empty vectors occupy minimal space in
1551debfc3dSmrg the structure containing them.
1561debfc3dSmrg
1571debfc3dSmrg Properties:
1581debfc3dSmrg
1591debfc3dSmrg - The whole vector and control data are allocated in a single
1601debfc3dSmrg contiguous block.
1611debfc3dSmrg - The whole vector may be re-allocated.
1621debfc3dSmrg - Vector data may grow and shrink.
1631debfc3dSmrg - Access and manipulation requires a pointer test and
1641debfc3dSmrg indirection.
1651debfc3dSmrg - It requires 1 word of storage (prior to vector allocation).
1661debfc3dSmrg
1671debfc3dSmrg An example of their use would be,
1681debfc3dSmrg
1691debfc3dSmrg struct my_struct {
1701debfc3dSmrg // A space-efficient vector of tree pointers in GC memory.
1711debfc3dSmrg vec<tree, va_gc, vl_ptr> v;
1721debfc3dSmrg };
1731debfc3dSmrg
1741debfc3dSmrg struct my_struct *s;
1751debfc3dSmrg
1761debfc3dSmrg if (s->v.length ()) { we have some contents }
1771debfc3dSmrg s->v.safe_push (decl); // append some decl onto the end
1781debfc3dSmrg for (ix = 0; s->v.iterate (ix, &elt); ix++)
1791debfc3dSmrg { do something with elt }
1801debfc3dSmrg */
1811debfc3dSmrg
1821debfc3dSmrg /* Support function for statistics. */
1831debfc3dSmrg extern void dump_vec_loc_statistics (void);
1841debfc3dSmrg
1851debfc3dSmrg /* Hashtable mapping vec addresses to descriptors. */
1861debfc3dSmrg extern htab_t vec_mem_usage_hash;
1871debfc3dSmrg
1881debfc3dSmrg /* Control data for vectors. This contains the number of allocated
1891debfc3dSmrg and used slots inside a vector. */
1901debfc3dSmrg
1911debfc3dSmrg struct vec_prefix
1921debfc3dSmrg {
1931debfc3dSmrg /* FIXME - These fields should be private, but we need to cater to
1941debfc3dSmrg compilers that have stricter notions of PODness for types. */
1951debfc3dSmrg
1961debfc3dSmrg /* Memory allocation support routines in vec.c. */
1971debfc3dSmrg void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO);
198c0a68be4Smrg void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO);
1991debfc3dSmrg static unsigned calculate_allocation (vec_prefix *, unsigned, bool);
2001debfc3dSmrg static unsigned calculate_allocation_1 (unsigned, unsigned);
2011debfc3dSmrg
2021debfc3dSmrg /* Note that vec_prefix should be a base class for vec, but we use
2031debfc3dSmrg offsetof() on vector fields of tree structures (e.g.,
2041debfc3dSmrg tree_binfo::base_binfos), and offsetof only supports base types.
2051debfc3dSmrg
2061debfc3dSmrg To compensate, we make vec_prefix a field inside vec and make
2071debfc3dSmrg vec a friend class of vec_prefix so it can access its fields. */
2081debfc3dSmrg template <typename, typename, typename> friend struct vec;
2091debfc3dSmrg
2101debfc3dSmrg /* The allocator types also need access to our internals. */
2111debfc3dSmrg friend struct va_gc;
2121debfc3dSmrg friend struct va_gc_atomic;
2131debfc3dSmrg friend struct va_heap;
2141debfc3dSmrg
2151debfc3dSmrg unsigned m_alloc : 31;
2161debfc3dSmrg unsigned m_using_auto_storage : 1;
2171debfc3dSmrg unsigned m_num;
2181debfc3dSmrg };
2191debfc3dSmrg
2201debfc3dSmrg /* Calculate the number of slots to reserve a vector, making sure that
2211debfc3dSmrg RESERVE slots are free. If EXACT grow exactly, otherwise grow
2221debfc3dSmrg exponentially. PFX is the control data for the vector. */
2231debfc3dSmrg
2241debfc3dSmrg inline unsigned
calculate_allocation(vec_prefix * pfx,unsigned reserve,bool exact)2251debfc3dSmrg vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
2261debfc3dSmrg bool exact)
2271debfc3dSmrg {
2281debfc3dSmrg if (exact)
2291debfc3dSmrg return (pfx ? pfx->m_num : 0) + reserve;
2301debfc3dSmrg else if (!pfx)
2311debfc3dSmrg return MAX (4, reserve);
2321debfc3dSmrg return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve);
2331debfc3dSmrg }
2341debfc3dSmrg
2351debfc3dSmrg template<typename, typename, typename> struct vec;
2361debfc3dSmrg
2371debfc3dSmrg /* Valid vector layouts
2381debfc3dSmrg
2391debfc3dSmrg vl_embed - Embeddable vector that uses the trailing array idiom.
2401debfc3dSmrg vl_ptr - Space efficient vector that uses a pointer to an
2411debfc3dSmrg embeddable vector. */
2421debfc3dSmrg struct vl_embed { };
2431debfc3dSmrg struct vl_ptr { };
2441debfc3dSmrg
2451debfc3dSmrg
2461debfc3dSmrg /* Types of supported allocations
2471debfc3dSmrg
2481debfc3dSmrg va_heap - Allocation uses malloc/free.
2491debfc3dSmrg va_gc - Allocation uses ggc_alloc.
2501debfc3dSmrg va_gc_atomic - Same as GC, but individual elements of the array
2511debfc3dSmrg do not need to be marked during collection. */
2521debfc3dSmrg
2531debfc3dSmrg /* Allocator type for heap vectors. */
2541debfc3dSmrg struct va_heap
2551debfc3dSmrg {
2561debfc3dSmrg /* Heap vectors are frequently regular instances, so use the vl_ptr
2571debfc3dSmrg layout for them. */
2581debfc3dSmrg typedef vl_ptr default_layout;
2591debfc3dSmrg
2601debfc3dSmrg template<typename T>
2611debfc3dSmrg static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool
2621debfc3dSmrg CXX_MEM_STAT_INFO);
2631debfc3dSmrg
2641debfc3dSmrg template<typename T>
2651debfc3dSmrg static void release (vec<T, va_heap, vl_embed> *&);
2661debfc3dSmrg };
2671debfc3dSmrg
2681debfc3dSmrg
2691debfc3dSmrg /* Allocator for heap memory. Ensure there are at least RESERVE free
2701debfc3dSmrg slots in V. If EXACT is true, grow exactly, else grow
2711debfc3dSmrg exponentially. As a special case, if the vector had not been
2721debfc3dSmrg allocated and RESERVE is 0, no vector will be created. */
2731debfc3dSmrg
2741debfc3dSmrg template<typename T>
2751debfc3dSmrg inline void
reserve(vec<T,va_heap,vl_embed> * & v,unsigned reserve,bool exact MEM_STAT_DECL)2761debfc3dSmrg va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
2771debfc3dSmrg MEM_STAT_DECL)
2781debfc3dSmrg {
279c0a68be4Smrg size_t elt_size = sizeof (T);
2801debfc3dSmrg unsigned alloc
2811debfc3dSmrg = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
2821debfc3dSmrg gcc_checking_assert (alloc);
2831debfc3dSmrg
2841debfc3dSmrg if (GATHER_STATISTICS && v)
285c0a68be4Smrg v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
286c0a68be4Smrg v->allocated (), false);
2871debfc3dSmrg
2881debfc3dSmrg size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
2891debfc3dSmrg unsigned nelem = v ? v->length () : 0;
2901debfc3dSmrg v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size));
2911debfc3dSmrg v->embedded_init (alloc, nelem);
2921debfc3dSmrg
2931debfc3dSmrg if (GATHER_STATISTICS)
294c0a68be4Smrg v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT);
2951debfc3dSmrg }
2961debfc3dSmrg
2971debfc3dSmrg
298*8feb0f0bSmrg #if GCC_VERSION >= 4007
299*8feb0f0bSmrg #pragma GCC diagnostic push
300*8feb0f0bSmrg #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
301*8feb0f0bSmrg #endif
302*8feb0f0bSmrg
3031debfc3dSmrg /* Free the heap space allocated for vector V. */
3041debfc3dSmrg
3051debfc3dSmrg template<typename T>
3061debfc3dSmrg void
release(vec<T,va_heap,vl_embed> * & v)3071debfc3dSmrg va_heap::release (vec<T, va_heap, vl_embed> *&v)
3081debfc3dSmrg {
309c0a68be4Smrg size_t elt_size = sizeof (T);
3101debfc3dSmrg if (v == NULL)
3111debfc3dSmrg return;
3121debfc3dSmrg
3131debfc3dSmrg if (GATHER_STATISTICS)
314c0a68be4Smrg v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
315c0a68be4Smrg v->allocated (), true);
3161debfc3dSmrg ::free (v);
3171debfc3dSmrg v = NULL;
3181debfc3dSmrg }
3191debfc3dSmrg
320*8feb0f0bSmrg #if GCC_VERSION >= 4007
321*8feb0f0bSmrg #pragma GCC diagnostic pop
322*8feb0f0bSmrg #endif
3231debfc3dSmrg
3241debfc3dSmrg /* Allocator type for GC vectors. Notice that we need the structure
3251debfc3dSmrg declaration even if GC is not enabled. */
3261debfc3dSmrg
3271debfc3dSmrg struct va_gc
3281debfc3dSmrg {
3291debfc3dSmrg /* Use vl_embed as the default layout for GC vectors. Due to GTY
3301debfc3dSmrg limitations, GC vectors must always be pointers, so it is more
3311debfc3dSmrg efficient to use a pointer to the vl_embed layout, rather than
3321debfc3dSmrg using a pointer to a pointer as would be the case with vl_ptr. */
3331debfc3dSmrg typedef vl_embed default_layout;
3341debfc3dSmrg
3351debfc3dSmrg template<typename T, typename A>
3361debfc3dSmrg static void reserve (vec<T, A, vl_embed> *&, unsigned, bool
3371debfc3dSmrg CXX_MEM_STAT_INFO);
3381debfc3dSmrg
3391debfc3dSmrg template<typename T, typename A>
3401debfc3dSmrg static void release (vec<T, A, vl_embed> *&v);
3411debfc3dSmrg };
3421debfc3dSmrg
3431debfc3dSmrg
3441debfc3dSmrg /* Free GC memory used by V and reset V to NULL. */
3451debfc3dSmrg
3461debfc3dSmrg template<typename T, typename A>
3471debfc3dSmrg inline void
release(vec<T,A,vl_embed> * & v)3481debfc3dSmrg va_gc::release (vec<T, A, vl_embed> *&v)
3491debfc3dSmrg {
3501debfc3dSmrg if (v)
3511debfc3dSmrg ::ggc_free (v);
3521debfc3dSmrg v = NULL;
3531debfc3dSmrg }
3541debfc3dSmrg
3551debfc3dSmrg
3561debfc3dSmrg /* Allocator for GC memory. Ensure there are at least RESERVE free
3571debfc3dSmrg slots in V. If EXACT is true, grow exactly, else grow
3581debfc3dSmrg exponentially. As a special case, if the vector had not been
3591debfc3dSmrg allocated and RESERVE is 0, no vector will be created. */
3601debfc3dSmrg
3611debfc3dSmrg template<typename T, typename A>
3621debfc3dSmrg void
reserve(vec<T,A,vl_embed> * & v,unsigned reserve,bool exact MEM_STAT_DECL)3631debfc3dSmrg va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
3641debfc3dSmrg MEM_STAT_DECL)
3651debfc3dSmrg {
3661debfc3dSmrg unsigned alloc
3671debfc3dSmrg = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
3681debfc3dSmrg if (!alloc)
3691debfc3dSmrg {
3701debfc3dSmrg ::ggc_free (v);
3711debfc3dSmrg v = NULL;
3721debfc3dSmrg return;
3731debfc3dSmrg }
3741debfc3dSmrg
3751debfc3dSmrg /* Calculate the amount of space we want. */
3761debfc3dSmrg size_t size = vec<T, A, vl_embed>::embedded_size (alloc);
3771debfc3dSmrg
3781debfc3dSmrg /* Ask the allocator how much space it will really give us. */
3791debfc3dSmrg size = ::ggc_round_alloc_size (size);
3801debfc3dSmrg
3811debfc3dSmrg /* Adjust the number of slots accordingly. */
3821debfc3dSmrg size_t vec_offset = sizeof (vec_prefix);
3831debfc3dSmrg size_t elt_size = sizeof (T);
3841debfc3dSmrg alloc = (size - vec_offset) / elt_size;
3851debfc3dSmrg
3861debfc3dSmrg /* And finally, recalculate the amount of space we ask for. */
3871debfc3dSmrg size = vec_offset + alloc * elt_size;
3881debfc3dSmrg
3891debfc3dSmrg unsigned nelem = v ? v->length () : 0;
3901debfc3dSmrg v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
3911debfc3dSmrg PASS_MEM_STAT));
3921debfc3dSmrg v->embedded_init (alloc, nelem);
3931debfc3dSmrg }
3941debfc3dSmrg
3951debfc3dSmrg
3961debfc3dSmrg /* Allocator type for GC vectors. This is for vectors of types
3971debfc3dSmrg atomics w.r.t. collection, so allocation and deallocation is
3981debfc3dSmrg completely inherited from va_gc. */
3991debfc3dSmrg struct va_gc_atomic : va_gc
4001debfc3dSmrg {
4011debfc3dSmrg };
4021debfc3dSmrg
4031debfc3dSmrg
4041debfc3dSmrg /* Generic vector template. Default values for A and L indicate the
4051debfc3dSmrg most commonly used strategies.
4061debfc3dSmrg
4071debfc3dSmrg FIXME - Ideally, they would all be vl_ptr to encourage using regular
4081debfc3dSmrg instances for vectors, but the existing GTY machinery is limited
4091debfc3dSmrg in that it can only deal with GC objects that are pointers
4101debfc3dSmrg themselves.
4111debfc3dSmrg
4121debfc3dSmrg This means that vector operations that need to deal with
4131debfc3dSmrg potentially NULL pointers, must be provided as free
4141debfc3dSmrg functions (see the vec_safe_* functions above). */
4151debfc3dSmrg template<typename T,
4161debfc3dSmrg typename A = va_heap,
4171debfc3dSmrg typename L = typename A::default_layout>
4181debfc3dSmrg struct GTY((user)) vec
4191debfc3dSmrg {
4201debfc3dSmrg };
4211debfc3dSmrg
422a2dc1f3fSmrg /* Generic vec<> debug helpers.
423a2dc1f3fSmrg
424a2dc1f3fSmrg These need to be instantiated for each vec<TYPE> used throughout
425a2dc1f3fSmrg the compiler like this:
426a2dc1f3fSmrg
427a2dc1f3fSmrg DEFINE_DEBUG_VEC (TYPE)
428a2dc1f3fSmrg
429a2dc1f3fSmrg The reason we have a debug_helper() is because GDB can't
430a2dc1f3fSmrg disambiguate a plain call to debug(some_vec), and it must be called
431a2dc1f3fSmrg like debug<TYPE>(some_vec). */
432a2dc1f3fSmrg
433a2dc1f3fSmrg template<typename T>
434a2dc1f3fSmrg void
debug_helper(vec<T> & ref)435a2dc1f3fSmrg debug_helper (vec<T> &ref)
436a2dc1f3fSmrg {
437a2dc1f3fSmrg unsigned i;
438a2dc1f3fSmrg for (i = 0; i < ref.length (); ++i)
439a2dc1f3fSmrg {
440a2dc1f3fSmrg fprintf (stderr, "[%d] = ", i);
441a2dc1f3fSmrg debug_slim (ref[i]);
442a2dc1f3fSmrg fputc ('\n', stderr);
443a2dc1f3fSmrg }
444a2dc1f3fSmrg }
445a2dc1f3fSmrg
446a2dc1f3fSmrg /* We need a separate va_gc variant here because default template
447a2dc1f3fSmrg argument for functions cannot be used in c++-98. Once this
448a2dc1f3fSmrg restriction is removed, those variant should be folded with the
449a2dc1f3fSmrg above debug_helper. */
450a2dc1f3fSmrg
451a2dc1f3fSmrg template<typename T>
452a2dc1f3fSmrg void
debug_helper(vec<T,va_gc> & ref)453a2dc1f3fSmrg debug_helper (vec<T, va_gc> &ref)
454a2dc1f3fSmrg {
455a2dc1f3fSmrg unsigned i;
456a2dc1f3fSmrg for (i = 0; i < ref.length (); ++i)
457a2dc1f3fSmrg {
458a2dc1f3fSmrg fprintf (stderr, "[%d] = ", i);
459a2dc1f3fSmrg debug_slim (ref[i]);
460a2dc1f3fSmrg fputc ('\n', stderr);
461a2dc1f3fSmrg }
462a2dc1f3fSmrg }
463a2dc1f3fSmrg
464a2dc1f3fSmrg /* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper
465a2dc1f3fSmrg functions for a type T. */
466a2dc1f3fSmrg
467a2dc1f3fSmrg #define DEFINE_DEBUG_VEC(T) \
468a2dc1f3fSmrg template void debug_helper (vec<T> &); \
469a2dc1f3fSmrg template void debug_helper (vec<T, va_gc> &); \
470a2dc1f3fSmrg /* Define the vec<T> debug functions. */ \
471a2dc1f3fSmrg DEBUG_FUNCTION void \
472a2dc1f3fSmrg debug (vec<T> &ref) \
473a2dc1f3fSmrg { \
474a2dc1f3fSmrg debug_helper <T> (ref); \
475a2dc1f3fSmrg } \
476a2dc1f3fSmrg DEBUG_FUNCTION void \
477a2dc1f3fSmrg debug (vec<T> *ptr) \
478a2dc1f3fSmrg { \
479a2dc1f3fSmrg if (ptr) \
480a2dc1f3fSmrg debug (*ptr); \
481a2dc1f3fSmrg else \
482a2dc1f3fSmrg fprintf (stderr, "<nil>\n"); \
483a2dc1f3fSmrg } \
484a2dc1f3fSmrg /* Define the vec<T, va_gc> debug functions. */ \
485a2dc1f3fSmrg DEBUG_FUNCTION void \
486a2dc1f3fSmrg debug (vec<T, va_gc> &ref) \
487a2dc1f3fSmrg { \
488a2dc1f3fSmrg debug_helper <T> (ref); \
489a2dc1f3fSmrg } \
490a2dc1f3fSmrg DEBUG_FUNCTION void \
491a2dc1f3fSmrg debug (vec<T, va_gc> *ptr) \
492a2dc1f3fSmrg { \
493a2dc1f3fSmrg if (ptr) \
494a2dc1f3fSmrg debug (*ptr); \
495a2dc1f3fSmrg else \
496a2dc1f3fSmrg fprintf (stderr, "<nil>\n"); \
497a2dc1f3fSmrg }
498a2dc1f3fSmrg
499a2dc1f3fSmrg /* Default-construct N elements in DST. */
500a2dc1f3fSmrg
501a2dc1f3fSmrg template <typename T>
502a2dc1f3fSmrg inline void
vec_default_construct(T * dst,unsigned n)503a2dc1f3fSmrg vec_default_construct (T *dst, unsigned n)
504a2dc1f3fSmrg {
505a2dc1f3fSmrg #ifdef BROKEN_VALUE_INITIALIZATION
506a2dc1f3fSmrg /* Versions of GCC before 4.4 sometimes leave certain objects
507a2dc1f3fSmrg uninitialized when value initialized, though if the type has
508a2dc1f3fSmrg user defined default ctor, that ctor is invoked. As a workaround
509a2dc1f3fSmrg perform clearing first and then the value initialization, which
510a2dc1f3fSmrg fixes the case when value initialization doesn't initialize due to
511a2dc1f3fSmrg the bugs and should initialize to all zeros, but still allows
512a2dc1f3fSmrg vectors for types with user defined default ctor that initializes
513a2dc1f3fSmrg some or all elements to non-zero. If T has no user defined
514a2dc1f3fSmrg default ctor and some non-static data members have user defined
515a2dc1f3fSmrg default ctors that initialize to non-zero the workaround will
516a2dc1f3fSmrg still not work properly; in that case we just need to provide
517a2dc1f3fSmrg user defined default ctor. */
518a2dc1f3fSmrg memset (dst, '\0', sizeof (T) * n);
519a2dc1f3fSmrg #endif
520a2dc1f3fSmrg for ( ; n; ++dst, --n)
521a2dc1f3fSmrg ::new (static_cast<void*>(dst)) T ();
522a2dc1f3fSmrg }
523a2dc1f3fSmrg
524a2dc1f3fSmrg /* Copy-construct N elements in DST from *SRC. */
525a2dc1f3fSmrg
526a2dc1f3fSmrg template <typename T>
527a2dc1f3fSmrg inline void
vec_copy_construct(T * dst,const T * src,unsigned n)528a2dc1f3fSmrg vec_copy_construct (T *dst, const T *src, unsigned n)
529a2dc1f3fSmrg {
530a2dc1f3fSmrg for ( ; n; ++dst, ++src, --n)
531a2dc1f3fSmrg ::new (static_cast<void*>(dst)) T (*src);
532a2dc1f3fSmrg }
533a2dc1f3fSmrg
5341debfc3dSmrg /* Type to provide NULL values for vec<T, A, L>. This is used to
5351debfc3dSmrg provide nil initializers for vec instances. Since vec must be
5361debfc3dSmrg a POD, we cannot have proper ctor/dtor for it. To initialize
5371debfc3dSmrg a vec instance, you can assign it the value vNULL. This isn't
5381debfc3dSmrg needed for file-scope and function-local static vectors, which
5391debfc3dSmrg are zero-initialized by default. */
5401debfc3dSmrg struct vnull
5411debfc3dSmrg {
5421debfc3dSmrg template <typename T, typename A, typename L>
543a2dc1f3fSmrg CONSTEXPR operator vec<T, A, L> () { return vec<T, A, L>(); }
5441debfc3dSmrg };
5451debfc3dSmrg extern vnull vNULL;
5461debfc3dSmrg
5471debfc3dSmrg
5481debfc3dSmrg /* Embeddable vector. These vectors are suitable to be embedded
5491debfc3dSmrg in other data structures so that they can be pre-allocated in a
5501debfc3dSmrg contiguous memory block.
5511debfc3dSmrg
5521debfc3dSmrg Embeddable vectors are implemented using the trailing array idiom,
5531debfc3dSmrg thus they are not resizeable without changing the address of the
5541debfc3dSmrg vector object itself. This means you cannot have variables or
5551debfc3dSmrg fields of embeddable vector type -- always use a pointer to a
5561debfc3dSmrg vector. The one exception is the final field of a structure, which
5571debfc3dSmrg could be a vector type.
5581debfc3dSmrg
5591debfc3dSmrg You will have to use the embedded_size & embedded_init calls to
5601debfc3dSmrg create such objects, and they will not be resizeable (so the 'safe'
5611debfc3dSmrg allocation variants are not available).
5621debfc3dSmrg
5631debfc3dSmrg Properties:
5641debfc3dSmrg
5651debfc3dSmrg - The whole vector and control data are allocated in a single
5661debfc3dSmrg contiguous block. It uses the trailing-vector idiom, so
5671debfc3dSmrg allocation must reserve enough space for all the elements
5681debfc3dSmrg in the vector plus its control data.
5691debfc3dSmrg - The vector cannot be re-allocated.
5701debfc3dSmrg - The vector cannot grow nor shrink.
5711debfc3dSmrg - No indirections needed for access/manipulation.
5721debfc3dSmrg - It requires 2 words of storage (prior to vector allocation). */
5731debfc3dSmrg
5741debfc3dSmrg template<typename T, typename A>
5751debfc3dSmrg struct GTY((user)) vec<T, A, vl_embed>
5761debfc3dSmrg {
5771debfc3dSmrg public:
5781debfc3dSmrg unsigned allocated (void) const { return m_vecpfx.m_alloc; }
5791debfc3dSmrg unsigned length (void) const { return m_vecpfx.m_num; }
5801debfc3dSmrg bool is_empty (void) const { return m_vecpfx.m_num == 0; }
5811debfc3dSmrg T *address (void) { return m_vecdata; }
5821debfc3dSmrg const T *address (void) const { return m_vecdata; }
5831debfc3dSmrg T *begin () { return address (); }
5841debfc3dSmrg const T *begin () const { return address (); }
5851debfc3dSmrg T *end () { return address () + length (); }
5861debfc3dSmrg const T *end () const { return address () + length (); }
5871debfc3dSmrg const T &operator[] (unsigned) const;
5881debfc3dSmrg T &operator[] (unsigned);
5891debfc3dSmrg T &last (void);
5901debfc3dSmrg bool space (unsigned) const;
5911debfc3dSmrg bool iterate (unsigned, T *) const;
5921debfc3dSmrg bool iterate (unsigned, T **) const;
5931debfc3dSmrg vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
5941debfc3dSmrg void splice (const vec &);
5951debfc3dSmrg void splice (const vec *src);
5961debfc3dSmrg T *quick_push (const T &);
5971debfc3dSmrg T &pop (void);
5981debfc3dSmrg void truncate (unsigned);
5991debfc3dSmrg void quick_insert (unsigned, const T &);
6001debfc3dSmrg void ordered_remove (unsigned);
6011debfc3dSmrg void unordered_remove (unsigned);
6021debfc3dSmrg void block_remove (unsigned, unsigned);
6031debfc3dSmrg void qsort (int (*) (const void *, const void *));
604*8feb0f0bSmrg void sort (int (*) (const void *, const void *, void *), void *);
6051debfc3dSmrg T *bsearch (const void *key, int (*compar)(const void *, const void *));
606*8feb0f0bSmrg T *bsearch (const void *key,
607*8feb0f0bSmrg int (*compar)(const void *, const void *, void *), void *);
6081debfc3dSmrg unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
6091debfc3dSmrg bool contains (const T &search) const;
6101debfc3dSmrg static size_t embedded_size (unsigned);
6111debfc3dSmrg void embedded_init (unsigned, unsigned = 0, unsigned = 0);
6121debfc3dSmrg void quick_grow (unsigned len);
6131debfc3dSmrg void quick_grow_cleared (unsigned len);
6141debfc3dSmrg
6151debfc3dSmrg /* vec class can access our internal data and functions. */
6161debfc3dSmrg template <typename, typename, typename> friend struct vec;
6171debfc3dSmrg
6181debfc3dSmrg /* The allocator types also need access to our internals. */
6191debfc3dSmrg friend struct va_gc;
6201debfc3dSmrg friend struct va_gc_atomic;
6211debfc3dSmrg friend struct va_heap;
6221debfc3dSmrg
6231debfc3dSmrg /* FIXME - These fields should be private, but we need to cater to
6241debfc3dSmrg compilers that have stricter notions of PODness for types. */
6251debfc3dSmrg vec_prefix m_vecpfx;
6261debfc3dSmrg T m_vecdata[1];
6271debfc3dSmrg };
6281debfc3dSmrg
6291debfc3dSmrg
6301debfc3dSmrg /* Convenience wrapper functions to use when dealing with pointers to
6311debfc3dSmrg embedded vectors. Some functionality for these vectors must be
6321debfc3dSmrg provided via free functions for these reasons:
6331debfc3dSmrg
6341debfc3dSmrg 1- The pointer may be NULL (e.g., before initial allocation).
6351debfc3dSmrg
6361debfc3dSmrg 2- When the vector needs to grow, it must be reallocated, so
6371debfc3dSmrg the pointer will change its value.
6381debfc3dSmrg
6391debfc3dSmrg Because of limitations with the current GC machinery, all vectors
6401debfc3dSmrg in GC memory *must* be pointers. */
6411debfc3dSmrg
6421debfc3dSmrg
6431debfc3dSmrg /* If V contains no room for NELEMS elements, return false. Otherwise,
6441debfc3dSmrg return true. */
6451debfc3dSmrg template<typename T, typename A>
6461debfc3dSmrg inline bool
6471debfc3dSmrg vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
6481debfc3dSmrg {
6491debfc3dSmrg return v ? v->space (nelems) : nelems == 0;
6501debfc3dSmrg }
6511debfc3dSmrg
6521debfc3dSmrg
6531debfc3dSmrg /* If V is NULL, return 0. Otherwise, return V->length(). */
6541debfc3dSmrg template<typename T, typename A>
6551debfc3dSmrg inline unsigned
6561debfc3dSmrg vec_safe_length (const vec<T, A, vl_embed> *v)
6571debfc3dSmrg {
6581debfc3dSmrg return v ? v->length () : 0;
6591debfc3dSmrg }
6601debfc3dSmrg
6611debfc3dSmrg
6621debfc3dSmrg /* If V is NULL, return NULL. Otherwise, return V->address(). */
6631debfc3dSmrg template<typename T, typename A>
6641debfc3dSmrg inline T *
6651debfc3dSmrg vec_safe_address (vec<T, A, vl_embed> *v)
6661debfc3dSmrg {
6671debfc3dSmrg return v ? v->address () : NULL;
6681debfc3dSmrg }
6691debfc3dSmrg
6701debfc3dSmrg
6711debfc3dSmrg /* If V is NULL, return true. Otherwise, return V->is_empty(). */
6721debfc3dSmrg template<typename T, typename A>
6731debfc3dSmrg inline bool
6741debfc3dSmrg vec_safe_is_empty (vec<T, A, vl_embed> *v)
6751debfc3dSmrg {
6761debfc3dSmrg return v ? v->is_empty () : true;
6771debfc3dSmrg }
6781debfc3dSmrg
6791debfc3dSmrg /* If V does not have space for NELEMS elements, call
6801debfc3dSmrg V->reserve(NELEMS, EXACT). */
6811debfc3dSmrg template<typename T, typename A>
6821debfc3dSmrg inline bool
6831debfc3dSmrg vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
6841debfc3dSmrg CXX_MEM_STAT_INFO)
6851debfc3dSmrg {
6861debfc3dSmrg bool extend = nelems ? !vec_safe_space (v, nelems) : false;
6871debfc3dSmrg if (extend)
6881debfc3dSmrg A::reserve (v, nelems, exact PASS_MEM_STAT);
6891debfc3dSmrg return extend;
6901debfc3dSmrg }
6911debfc3dSmrg
6921debfc3dSmrg template<typename T, typename A>
6931debfc3dSmrg inline bool
6941debfc3dSmrg vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
6951debfc3dSmrg CXX_MEM_STAT_INFO)
6961debfc3dSmrg {
6971debfc3dSmrg return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
6981debfc3dSmrg }
6991debfc3dSmrg
7001debfc3dSmrg
7011debfc3dSmrg /* Allocate GC memory for V with space for NELEMS slots. If NELEMS
7021debfc3dSmrg is 0, V is initialized to NULL. */
7031debfc3dSmrg
7041debfc3dSmrg template<typename T, typename A>
7051debfc3dSmrg inline void
7061debfc3dSmrg vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
7071debfc3dSmrg {
7081debfc3dSmrg v = NULL;
7091debfc3dSmrg vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
7101debfc3dSmrg }
7111debfc3dSmrg
7121debfc3dSmrg
7131debfc3dSmrg /* Free the GC memory allocated by vector V and set it to NULL. */
7141debfc3dSmrg
7151debfc3dSmrg template<typename T, typename A>
7161debfc3dSmrg inline void
7171debfc3dSmrg vec_free (vec<T, A, vl_embed> *&v)
7181debfc3dSmrg {
7191debfc3dSmrg A::release (v);
7201debfc3dSmrg }
7211debfc3dSmrg
7221debfc3dSmrg
7231debfc3dSmrg /* Grow V to length LEN. Allocate it, if necessary. */
7241debfc3dSmrg template<typename T, typename A>
7251debfc3dSmrg inline void
7261debfc3dSmrg vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
7271debfc3dSmrg {
7281debfc3dSmrg unsigned oldlen = vec_safe_length (v);
7291debfc3dSmrg gcc_checking_assert (len >= oldlen);
7301debfc3dSmrg vec_safe_reserve_exact (v, len - oldlen PASS_MEM_STAT);
7311debfc3dSmrg v->quick_grow (len);
7321debfc3dSmrg }
7331debfc3dSmrg
7341debfc3dSmrg
7351debfc3dSmrg /* If V is NULL, allocate it. Call V->safe_grow_cleared(LEN). */
7361debfc3dSmrg template<typename T, typename A>
7371debfc3dSmrg inline void
7381debfc3dSmrg vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
7391debfc3dSmrg {
7401debfc3dSmrg unsigned oldlen = vec_safe_length (v);
7411debfc3dSmrg vec_safe_grow (v, len PASS_MEM_STAT);
742a2dc1f3fSmrg vec_default_construct (v->address () + oldlen, len - oldlen);
7431debfc3dSmrg }
7441debfc3dSmrg
7451debfc3dSmrg
746c0a68be4Smrg /* Assume V is not NULL. */
747c0a68be4Smrg
748c0a68be4Smrg template<typename T>
749c0a68be4Smrg inline void
750c0a68be4Smrg vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v,
751c0a68be4Smrg unsigned len CXX_MEM_STAT_INFO)
752c0a68be4Smrg {
753c0a68be4Smrg v->safe_grow_cleared (len PASS_MEM_STAT);
754c0a68be4Smrg }
755c0a68be4Smrg
756*8feb0f0bSmrg /* If V does not have space for NELEMS elements, call
757*8feb0f0bSmrg V->reserve(NELEMS, EXACT). */
758*8feb0f0bSmrg
759*8feb0f0bSmrg template<typename T>
760*8feb0f0bSmrg inline bool
761*8feb0f0bSmrg vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false
762*8feb0f0bSmrg CXX_MEM_STAT_INFO)
763*8feb0f0bSmrg {
764*8feb0f0bSmrg return v->reserve (nelems, exact);
765*8feb0f0bSmrg }
766*8feb0f0bSmrg
767c0a68be4Smrg
7681debfc3dSmrg /* If V is NULL return false, otherwise return V->iterate(IX, PTR). */
7691debfc3dSmrg template<typename T, typename A>
7701debfc3dSmrg inline bool
7711debfc3dSmrg vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
7721debfc3dSmrg {
7731debfc3dSmrg if (v)
7741debfc3dSmrg return v->iterate (ix, ptr);
7751debfc3dSmrg else
7761debfc3dSmrg {
7771debfc3dSmrg *ptr = 0;
7781debfc3dSmrg return false;
7791debfc3dSmrg }
7801debfc3dSmrg }
7811debfc3dSmrg
7821debfc3dSmrg template<typename T, typename A>
7831debfc3dSmrg inline bool
7841debfc3dSmrg vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
7851debfc3dSmrg {
7861debfc3dSmrg if (v)
7871debfc3dSmrg return v->iterate (ix, ptr);
7881debfc3dSmrg else
7891debfc3dSmrg {
7901debfc3dSmrg *ptr = 0;
7911debfc3dSmrg return false;
7921debfc3dSmrg }
7931debfc3dSmrg }
7941debfc3dSmrg
7951debfc3dSmrg
7961debfc3dSmrg /* If V has no room for one more element, reallocate it. Then call
7971debfc3dSmrg V->quick_push(OBJ). */
7981debfc3dSmrg template<typename T, typename A>
7991debfc3dSmrg inline T *
8001debfc3dSmrg vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
8011debfc3dSmrg {
8021debfc3dSmrg vec_safe_reserve (v, 1, false PASS_MEM_STAT);
8031debfc3dSmrg return v->quick_push (obj);
8041debfc3dSmrg }
8051debfc3dSmrg
8061debfc3dSmrg
8071debfc3dSmrg /* if V has no room for one more element, reallocate it. Then call
8081debfc3dSmrg V->quick_insert(IX, OBJ). */
8091debfc3dSmrg template<typename T, typename A>
8101debfc3dSmrg inline void
8111debfc3dSmrg vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
8121debfc3dSmrg CXX_MEM_STAT_INFO)
8131debfc3dSmrg {
8141debfc3dSmrg vec_safe_reserve (v, 1, false PASS_MEM_STAT);
8151debfc3dSmrg v->quick_insert (ix, obj);
8161debfc3dSmrg }
8171debfc3dSmrg
8181debfc3dSmrg
8191debfc3dSmrg /* If V is NULL, do nothing. Otherwise, call V->truncate(SIZE). */
8201debfc3dSmrg template<typename T, typename A>
8211debfc3dSmrg inline void
8221debfc3dSmrg vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
8231debfc3dSmrg {
8241debfc3dSmrg if (v)
8251debfc3dSmrg v->truncate (size);
8261debfc3dSmrg }
8271debfc3dSmrg
8281debfc3dSmrg
8291debfc3dSmrg /* If SRC is not NULL, return a pointer to a copy of it. */
8301debfc3dSmrg template<typename T, typename A>
8311debfc3dSmrg inline vec<T, A, vl_embed> *
8321debfc3dSmrg vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
8331debfc3dSmrg {
8341debfc3dSmrg return src ? src->copy (ALONE_PASS_MEM_STAT) : NULL;
8351debfc3dSmrg }
8361debfc3dSmrg
8371debfc3dSmrg /* Copy the elements from SRC to the end of DST as if by memcpy.
8381debfc3dSmrg Reallocate DST, if necessary. */
8391debfc3dSmrg template<typename T, typename A>
8401debfc3dSmrg inline void
8411debfc3dSmrg vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
8421debfc3dSmrg CXX_MEM_STAT_INFO)
8431debfc3dSmrg {
8441debfc3dSmrg unsigned src_len = vec_safe_length (src);
8451debfc3dSmrg if (src_len)
8461debfc3dSmrg {
8471debfc3dSmrg vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
8481debfc3dSmrg PASS_MEM_STAT);
8491debfc3dSmrg dst->splice (*src);
8501debfc3dSmrg }
8511debfc3dSmrg }
8521debfc3dSmrg
8531debfc3dSmrg /* Return true if SEARCH is an element of V. Note that this is O(N) in the
8541debfc3dSmrg size of the vector and so should be used with care. */
8551debfc3dSmrg
8561debfc3dSmrg template<typename T, typename A>
8571debfc3dSmrg inline bool
8581debfc3dSmrg vec_safe_contains (vec<T, A, vl_embed> *v, const T &search)
8591debfc3dSmrg {
8601debfc3dSmrg return v ? v->contains (search) : false;
8611debfc3dSmrg }
8621debfc3dSmrg
8631debfc3dSmrg /* Index into vector. Return the IX'th element. IX must be in the
8641debfc3dSmrg domain of the vector. */
8651debfc3dSmrg
8661debfc3dSmrg template<typename T, typename A>
8671debfc3dSmrg inline const T &
8681debfc3dSmrg vec<T, A, vl_embed>::operator[] (unsigned ix) const
8691debfc3dSmrg {
8701debfc3dSmrg gcc_checking_assert (ix < m_vecpfx.m_num);
8711debfc3dSmrg return m_vecdata[ix];
8721debfc3dSmrg }
8731debfc3dSmrg
8741debfc3dSmrg template<typename T, typename A>
8751debfc3dSmrg inline T &
8761debfc3dSmrg vec<T, A, vl_embed>::operator[] (unsigned ix)
8771debfc3dSmrg {
8781debfc3dSmrg gcc_checking_assert (ix < m_vecpfx.m_num);
8791debfc3dSmrg return m_vecdata[ix];
8801debfc3dSmrg }
8811debfc3dSmrg
8821debfc3dSmrg
8831debfc3dSmrg /* Get the final element of the vector, which must not be empty. */
8841debfc3dSmrg
8851debfc3dSmrg template<typename T, typename A>
8861debfc3dSmrg inline T &
8871debfc3dSmrg vec<T, A, vl_embed>::last (void)
8881debfc3dSmrg {
8891debfc3dSmrg gcc_checking_assert (m_vecpfx.m_num > 0);
8901debfc3dSmrg return (*this)[m_vecpfx.m_num - 1];
8911debfc3dSmrg }
8921debfc3dSmrg
8931debfc3dSmrg
8941debfc3dSmrg /* If this vector has space for NELEMS additional entries, return
8951debfc3dSmrg true. You usually only need to use this if you are doing your
8961debfc3dSmrg own vector reallocation, for instance on an embedded vector. This
8971debfc3dSmrg returns true in exactly the same circumstances that vec::reserve
8981debfc3dSmrg will. */
8991debfc3dSmrg
9001debfc3dSmrg template<typename T, typename A>
9011debfc3dSmrg inline bool
9021debfc3dSmrg vec<T, A, vl_embed>::space (unsigned nelems) const
9031debfc3dSmrg {
9041debfc3dSmrg return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
9051debfc3dSmrg }
9061debfc3dSmrg
9071debfc3dSmrg
9081debfc3dSmrg /* Return iteration condition and update PTR to point to the IX'th
9091debfc3dSmrg element of this vector. Use this to iterate over the elements of a
9101debfc3dSmrg vector as follows,
9111debfc3dSmrg
9121debfc3dSmrg for (ix = 0; vec<T, A>::iterate (v, ix, &ptr); ix++)
9131debfc3dSmrg continue; */
9141debfc3dSmrg
9151debfc3dSmrg template<typename T, typename A>
9161debfc3dSmrg inline bool
9171debfc3dSmrg vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
9181debfc3dSmrg {
9191debfc3dSmrg if (ix < m_vecpfx.m_num)
9201debfc3dSmrg {
9211debfc3dSmrg *ptr = m_vecdata[ix];
9221debfc3dSmrg return true;
9231debfc3dSmrg }
9241debfc3dSmrg else
9251debfc3dSmrg {
9261debfc3dSmrg *ptr = 0;
9271debfc3dSmrg return false;
9281debfc3dSmrg }
9291debfc3dSmrg }
9301debfc3dSmrg
9311debfc3dSmrg
9321debfc3dSmrg /* Return iteration condition and update *PTR to point to the
9331debfc3dSmrg IX'th element of this vector. Use this to iterate over the
9341debfc3dSmrg elements of a vector as follows,
9351debfc3dSmrg
9361debfc3dSmrg for (ix = 0; v->iterate (ix, &ptr); ix++)
9371debfc3dSmrg continue;
9381debfc3dSmrg
9391debfc3dSmrg This variant is for vectors of objects. */
9401debfc3dSmrg
9411debfc3dSmrg template<typename T, typename A>
9421debfc3dSmrg inline bool
9431debfc3dSmrg vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
9441debfc3dSmrg {
9451debfc3dSmrg if (ix < m_vecpfx.m_num)
9461debfc3dSmrg {
9471debfc3dSmrg *ptr = CONST_CAST (T *, &m_vecdata[ix]);
9481debfc3dSmrg return true;
9491debfc3dSmrg }
9501debfc3dSmrg else
9511debfc3dSmrg {
9521debfc3dSmrg *ptr = 0;
9531debfc3dSmrg return false;
9541debfc3dSmrg }
9551debfc3dSmrg }
9561debfc3dSmrg
9571debfc3dSmrg
9581debfc3dSmrg /* Return a pointer to a copy of this vector. */
9591debfc3dSmrg
9601debfc3dSmrg template<typename T, typename A>
9611debfc3dSmrg inline vec<T, A, vl_embed> *
9621debfc3dSmrg vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
9631debfc3dSmrg {
9641debfc3dSmrg vec<T, A, vl_embed> *new_vec = NULL;
9651debfc3dSmrg unsigned len = length ();
9661debfc3dSmrg if (len)
9671debfc3dSmrg {
9681debfc3dSmrg vec_alloc (new_vec, len PASS_MEM_STAT);
9691debfc3dSmrg new_vec->embedded_init (len, len);
970a2dc1f3fSmrg vec_copy_construct (new_vec->address (), m_vecdata, len);
9711debfc3dSmrg }
9721debfc3dSmrg return new_vec;
9731debfc3dSmrg }
9741debfc3dSmrg
9751debfc3dSmrg
9761debfc3dSmrg /* Copy the elements from SRC to the end of this vector as if by memcpy.
9771debfc3dSmrg The vector must have sufficient headroom available. */
9781debfc3dSmrg
9791debfc3dSmrg template<typename T, typename A>
9801debfc3dSmrg inline void
9811debfc3dSmrg vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
9821debfc3dSmrg {
9831debfc3dSmrg unsigned len = src.length ();
9841debfc3dSmrg if (len)
9851debfc3dSmrg {
9861debfc3dSmrg gcc_checking_assert (space (len));
987a2dc1f3fSmrg vec_copy_construct (end (), src.address (), len);
9881debfc3dSmrg m_vecpfx.m_num += len;
9891debfc3dSmrg }
9901debfc3dSmrg }
9911debfc3dSmrg
9921debfc3dSmrg template<typename T, typename A>
9931debfc3dSmrg inline void
9941debfc3dSmrg vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
9951debfc3dSmrg {
9961debfc3dSmrg if (src)
9971debfc3dSmrg splice (*src);
9981debfc3dSmrg }
9991debfc3dSmrg
10001debfc3dSmrg
10011debfc3dSmrg /* Push OBJ (a new element) onto the end of the vector. There must be
10021debfc3dSmrg sufficient space in the vector. Return a pointer to the slot
10031debfc3dSmrg where OBJ was inserted. */
10041debfc3dSmrg
10051debfc3dSmrg template<typename T, typename A>
10061debfc3dSmrg inline T *
10071debfc3dSmrg vec<T, A, vl_embed>::quick_push (const T &obj)
10081debfc3dSmrg {
10091debfc3dSmrg gcc_checking_assert (space (1));
10101debfc3dSmrg T *slot = &m_vecdata[m_vecpfx.m_num++];
10111debfc3dSmrg *slot = obj;
10121debfc3dSmrg return slot;
10131debfc3dSmrg }
10141debfc3dSmrg
10151debfc3dSmrg
10161debfc3dSmrg /* Pop and return the last element off the end of the vector. */
10171debfc3dSmrg
10181debfc3dSmrg template<typename T, typename A>
10191debfc3dSmrg inline T &
10201debfc3dSmrg vec<T, A, vl_embed>::pop (void)
10211debfc3dSmrg {
10221debfc3dSmrg gcc_checking_assert (length () > 0);
10231debfc3dSmrg return m_vecdata[--m_vecpfx.m_num];
10241debfc3dSmrg }
10251debfc3dSmrg
10261debfc3dSmrg
10271debfc3dSmrg /* Set the length of the vector to SIZE. The new length must be less
10281debfc3dSmrg than or equal to the current length. This is an O(1) operation. */
10291debfc3dSmrg
10301debfc3dSmrg template<typename T, typename A>
10311debfc3dSmrg inline void
10321debfc3dSmrg vec<T, A, vl_embed>::truncate (unsigned size)
10331debfc3dSmrg {
10341debfc3dSmrg gcc_checking_assert (length () >= size);
10351debfc3dSmrg m_vecpfx.m_num = size;
10361debfc3dSmrg }
10371debfc3dSmrg
10381debfc3dSmrg
10391debfc3dSmrg /* Insert an element, OBJ, at the IXth position of this vector. There
10401debfc3dSmrg must be sufficient space. */
10411debfc3dSmrg
10421debfc3dSmrg template<typename T, typename A>
10431debfc3dSmrg inline void
10441debfc3dSmrg vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
10451debfc3dSmrg {
10461debfc3dSmrg gcc_checking_assert (length () < allocated ());
10471debfc3dSmrg gcc_checking_assert (ix <= length ());
10481debfc3dSmrg T *slot = &m_vecdata[ix];
10491debfc3dSmrg memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
10501debfc3dSmrg *slot = obj;
10511debfc3dSmrg }
10521debfc3dSmrg
10531debfc3dSmrg
10541debfc3dSmrg /* Remove an element from the IXth position of this vector. Ordering of
10551debfc3dSmrg remaining elements is preserved. This is an O(N) operation due to
10561debfc3dSmrg memmove. */
10571debfc3dSmrg
10581debfc3dSmrg template<typename T, typename A>
10591debfc3dSmrg inline void
10601debfc3dSmrg vec<T, A, vl_embed>::ordered_remove (unsigned ix)
10611debfc3dSmrg {
10621debfc3dSmrg gcc_checking_assert (ix < length ());
10631debfc3dSmrg T *slot = &m_vecdata[ix];
10641debfc3dSmrg memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
10651debfc3dSmrg }
10661debfc3dSmrg
10671debfc3dSmrg
1068c0a68be4Smrg /* Remove elements in [START, END) from VEC for which COND holds. Ordering of
1069c0a68be4Smrg remaining elements is preserved. This is an O(N) operation. */
1070c0a68be4Smrg
1071c0a68be4Smrg #define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index, \
1072c0a68be4Smrg elem_ptr, start, end, cond) \
1073c0a68be4Smrg { \
1074c0a68be4Smrg gcc_assert ((end) <= (vec).length ()); \
1075c0a68be4Smrg for (read_index = write_index = (start); read_index < (end); \
1076c0a68be4Smrg ++read_index) \
1077c0a68be4Smrg { \
1078c0a68be4Smrg elem_ptr = &(vec)[read_index]; \
1079c0a68be4Smrg bool remove_p = (cond); \
1080c0a68be4Smrg if (remove_p) \
1081c0a68be4Smrg continue; \
1082c0a68be4Smrg \
1083c0a68be4Smrg if (read_index != write_index) \
1084c0a68be4Smrg (vec)[write_index] = (vec)[read_index]; \
1085c0a68be4Smrg \
1086c0a68be4Smrg write_index++; \
1087c0a68be4Smrg } \
1088c0a68be4Smrg \
1089c0a68be4Smrg if (read_index - write_index > 0) \
1090c0a68be4Smrg (vec).block_remove (write_index, read_index - write_index); \
1091c0a68be4Smrg }
1092c0a68be4Smrg
1093c0a68be4Smrg
1094c0a68be4Smrg /* Remove elements from VEC for which COND holds. Ordering of remaining
1095c0a68be4Smrg elements is preserved. This is an O(N) operation. */
1096c0a68be4Smrg
1097c0a68be4Smrg #define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr, \
1098c0a68be4Smrg cond) \
1099c0a68be4Smrg VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index, \
1100c0a68be4Smrg elem_ptr, 0, (vec).length (), (cond))
1101c0a68be4Smrg
11021debfc3dSmrg /* Remove an element from the IXth position of this vector. Ordering of
11031debfc3dSmrg remaining elements is destroyed. This is an O(1) operation. */
11041debfc3dSmrg
11051debfc3dSmrg template<typename T, typename A>
11061debfc3dSmrg inline void
11071debfc3dSmrg vec<T, A, vl_embed>::unordered_remove (unsigned ix)
11081debfc3dSmrg {
11091debfc3dSmrg gcc_checking_assert (ix < length ());
11101debfc3dSmrg m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num];
11111debfc3dSmrg }
11121debfc3dSmrg
11131debfc3dSmrg
11141debfc3dSmrg /* Remove LEN elements starting at the IXth. Ordering is retained.
11151debfc3dSmrg This is an O(N) operation due to memmove. */
11161debfc3dSmrg
11171debfc3dSmrg template<typename T, typename A>
11181debfc3dSmrg inline void
11191debfc3dSmrg vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
11201debfc3dSmrg {
11211debfc3dSmrg gcc_checking_assert (ix + len <= length ());
11221debfc3dSmrg T *slot = &m_vecdata[ix];
11231debfc3dSmrg m_vecpfx.m_num -= len;
11241debfc3dSmrg memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
11251debfc3dSmrg }
11261debfc3dSmrg
11271debfc3dSmrg
11281debfc3dSmrg /* Sort the contents of this vector with qsort. CMP is the comparison
11291debfc3dSmrg function to pass to qsort. */
11301debfc3dSmrg
11311debfc3dSmrg template<typename T, typename A>
11321debfc3dSmrg inline void
11331debfc3dSmrg vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
11341debfc3dSmrg {
11351debfc3dSmrg if (length () > 1)
1136*8feb0f0bSmrg gcc_qsort (address (), length (), sizeof (T), cmp);
1137*8feb0f0bSmrg }
1138*8feb0f0bSmrg
1139*8feb0f0bSmrg /* Sort the contents of this vector with qsort. CMP is the comparison
1140*8feb0f0bSmrg function to pass to qsort. */
1141*8feb0f0bSmrg
1142*8feb0f0bSmrg template<typename T, typename A>
1143*8feb0f0bSmrg inline void
1144*8feb0f0bSmrg vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *),
1145*8feb0f0bSmrg void *data)
1146*8feb0f0bSmrg {
1147*8feb0f0bSmrg if (length () > 1)
1148*8feb0f0bSmrg gcc_sort_r (address (), length (), sizeof (T), cmp, data);
11491debfc3dSmrg }
11501debfc3dSmrg
11511debfc3dSmrg
11521debfc3dSmrg /* Search the contents of the sorted vector with a binary search.
11531debfc3dSmrg CMP is the comparison function to pass to bsearch. */
11541debfc3dSmrg
11551debfc3dSmrg template<typename T, typename A>
11561debfc3dSmrg inline T *
11571debfc3dSmrg vec<T, A, vl_embed>::bsearch (const void *key,
11581debfc3dSmrg int (*compar) (const void *, const void *))
11591debfc3dSmrg {
11601debfc3dSmrg const void *base = this->address ();
11611debfc3dSmrg size_t nmemb = this->length ();
11621debfc3dSmrg size_t size = sizeof (T);
11631debfc3dSmrg /* The following is a copy of glibc stdlib-bsearch.h. */
11641debfc3dSmrg size_t l, u, idx;
11651debfc3dSmrg const void *p;
11661debfc3dSmrg int comparison;
11671debfc3dSmrg
11681debfc3dSmrg l = 0;
11691debfc3dSmrg u = nmemb;
11701debfc3dSmrg while (l < u)
11711debfc3dSmrg {
11721debfc3dSmrg idx = (l + u) / 2;
11731debfc3dSmrg p = (const void *) (((const char *) base) + (idx * size));
11741debfc3dSmrg comparison = (*compar) (key, p);
11751debfc3dSmrg if (comparison < 0)
11761debfc3dSmrg u = idx;
11771debfc3dSmrg else if (comparison > 0)
11781debfc3dSmrg l = idx + 1;
11791debfc3dSmrg else
11801debfc3dSmrg return (T *)const_cast<void *>(p);
11811debfc3dSmrg }
11821debfc3dSmrg
11831debfc3dSmrg return NULL;
11841debfc3dSmrg }
11851debfc3dSmrg
1186*8feb0f0bSmrg /* Search the contents of the sorted vector with a binary search.
1187*8feb0f0bSmrg CMP is the comparison function to pass to bsearch. */
1188*8feb0f0bSmrg
1189*8feb0f0bSmrg template<typename T, typename A>
1190*8feb0f0bSmrg inline T *
1191*8feb0f0bSmrg vec<T, A, vl_embed>::bsearch (const void *key,
1192*8feb0f0bSmrg int (*compar) (const void *, const void *,
1193*8feb0f0bSmrg void *), void *data)
1194*8feb0f0bSmrg {
1195*8feb0f0bSmrg const void *base = this->address ();
1196*8feb0f0bSmrg size_t nmemb = this->length ();
1197*8feb0f0bSmrg size_t size = sizeof (T);
1198*8feb0f0bSmrg /* The following is a copy of glibc stdlib-bsearch.h. */
1199*8feb0f0bSmrg size_t l, u, idx;
1200*8feb0f0bSmrg const void *p;
1201*8feb0f0bSmrg int comparison;
1202*8feb0f0bSmrg
1203*8feb0f0bSmrg l = 0;
1204*8feb0f0bSmrg u = nmemb;
1205*8feb0f0bSmrg while (l < u)
1206*8feb0f0bSmrg {
1207*8feb0f0bSmrg idx = (l + u) / 2;
1208*8feb0f0bSmrg p = (const void *) (((const char *) base) + (idx * size));
1209*8feb0f0bSmrg comparison = (*compar) (key, p, data);
1210*8feb0f0bSmrg if (comparison < 0)
1211*8feb0f0bSmrg u = idx;
1212*8feb0f0bSmrg else if (comparison > 0)
1213*8feb0f0bSmrg l = idx + 1;
1214*8feb0f0bSmrg else
1215*8feb0f0bSmrg return (T *)const_cast<void *>(p);
1216*8feb0f0bSmrg }
1217*8feb0f0bSmrg
1218*8feb0f0bSmrg return NULL;
1219*8feb0f0bSmrg }
1220*8feb0f0bSmrg
12211debfc3dSmrg /* Return true if SEARCH is an element of V. Note that this is O(N) in the
12221debfc3dSmrg size of the vector and so should be used with care. */
12231debfc3dSmrg
12241debfc3dSmrg template<typename T, typename A>
12251debfc3dSmrg inline bool
12261debfc3dSmrg vec<T, A, vl_embed>::contains (const T &search) const
12271debfc3dSmrg {
12281debfc3dSmrg unsigned int len = length ();
12291debfc3dSmrg for (unsigned int i = 0; i < len; i++)
12301debfc3dSmrg if ((*this)[i] == search)
12311debfc3dSmrg return true;
12321debfc3dSmrg
12331debfc3dSmrg return false;
12341debfc3dSmrg }
12351debfc3dSmrg
12361debfc3dSmrg /* Find and return the first position in which OBJ could be inserted
12371debfc3dSmrg without changing the ordering of this vector. LESSTHAN is a
12381debfc3dSmrg function that returns true if the first argument is strictly less
12391debfc3dSmrg than the second. */
12401debfc3dSmrg
12411debfc3dSmrg template<typename T, typename A>
12421debfc3dSmrg unsigned
12431debfc3dSmrg vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
12441debfc3dSmrg const
12451debfc3dSmrg {
12461debfc3dSmrg unsigned int len = length ();
12471debfc3dSmrg unsigned int half, middle;
12481debfc3dSmrg unsigned int first = 0;
12491debfc3dSmrg while (len > 0)
12501debfc3dSmrg {
12511debfc3dSmrg half = len / 2;
12521debfc3dSmrg middle = first;
12531debfc3dSmrg middle += half;
12541debfc3dSmrg T middle_elem = (*this)[middle];
12551debfc3dSmrg if (lessthan (middle_elem, obj))
12561debfc3dSmrg {
12571debfc3dSmrg first = middle;
12581debfc3dSmrg ++first;
12591debfc3dSmrg len = len - half - 1;
12601debfc3dSmrg }
12611debfc3dSmrg else
12621debfc3dSmrg len = half;
12631debfc3dSmrg }
12641debfc3dSmrg return first;
12651debfc3dSmrg }
12661debfc3dSmrg
12671debfc3dSmrg
12681debfc3dSmrg /* Return the number of bytes needed to embed an instance of an
12691debfc3dSmrg embeddable vec inside another data structure.
12701debfc3dSmrg
12711debfc3dSmrg Use these methods to determine the required size and initialization
12721debfc3dSmrg of a vector V of type T embedded within another structure (as the
12731debfc3dSmrg final member):
12741debfc3dSmrg
12751debfc3dSmrg size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
12761debfc3dSmrg void v->embedded_init (unsigned alloc, unsigned num);
12771debfc3dSmrg
12781debfc3dSmrg These allow the caller to perform the memory allocation. */
12791debfc3dSmrg
12801debfc3dSmrg template<typename T, typename A>
12811debfc3dSmrg inline size_t
12821debfc3dSmrg vec<T, A, vl_embed>::embedded_size (unsigned alloc)
12831debfc3dSmrg {
12841debfc3dSmrg typedef vec<T, A, vl_embed> vec_embedded;
12851debfc3dSmrg return offsetof (vec_embedded, m_vecdata) + alloc * sizeof (T);
12861debfc3dSmrg }
12871debfc3dSmrg
12881debfc3dSmrg
12891debfc3dSmrg /* Initialize the vector to contain room for ALLOC elements and
12901debfc3dSmrg NUM active elements. */
12911debfc3dSmrg
12921debfc3dSmrg template<typename T, typename A>
12931debfc3dSmrg inline void
12941debfc3dSmrg vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
12951debfc3dSmrg {
12961debfc3dSmrg m_vecpfx.m_alloc = alloc;
12971debfc3dSmrg m_vecpfx.m_using_auto_storage = aut;
12981debfc3dSmrg m_vecpfx.m_num = num;
12991debfc3dSmrg }
13001debfc3dSmrg
13011debfc3dSmrg
13021debfc3dSmrg /* Grow the vector to a specific length. LEN must be as long or longer than
13031debfc3dSmrg the current length. The new elements are uninitialized. */
13041debfc3dSmrg
13051debfc3dSmrg template<typename T, typename A>
13061debfc3dSmrg inline void
13071debfc3dSmrg vec<T, A, vl_embed>::quick_grow (unsigned len)
13081debfc3dSmrg {
13091debfc3dSmrg gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
13101debfc3dSmrg m_vecpfx.m_num = len;
13111debfc3dSmrg }
13121debfc3dSmrg
13131debfc3dSmrg
13141debfc3dSmrg /* Grow the vector to a specific length. LEN must be as long or longer than
13151debfc3dSmrg the current length. The new elements are initialized to zero. */
13161debfc3dSmrg
13171debfc3dSmrg template<typename T, typename A>
13181debfc3dSmrg inline void
13191debfc3dSmrg vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
13201debfc3dSmrg {
13211debfc3dSmrg unsigned oldlen = length ();
1322a2dc1f3fSmrg size_t growby = len - oldlen;
13231debfc3dSmrg quick_grow (len);
1324a2dc1f3fSmrg if (growby != 0)
1325a2dc1f3fSmrg vec_default_construct (address () + oldlen, growby);
13261debfc3dSmrg }
13271debfc3dSmrg
13281debfc3dSmrg /* Garbage collection support for vec<T, A, vl_embed>. */
13291debfc3dSmrg
13301debfc3dSmrg template<typename T>
13311debfc3dSmrg void
13321debfc3dSmrg gt_ggc_mx (vec<T, va_gc> *v)
13331debfc3dSmrg {
13341debfc3dSmrg extern void gt_ggc_mx (T &);
13351debfc3dSmrg for (unsigned i = 0; i < v->length (); i++)
13361debfc3dSmrg gt_ggc_mx ((*v)[i]);
13371debfc3dSmrg }
13381debfc3dSmrg
13391debfc3dSmrg template<typename T>
13401debfc3dSmrg void
13411debfc3dSmrg gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED)
13421debfc3dSmrg {
13431debfc3dSmrg /* Nothing to do. Vectors of atomic types wrt GC do not need to
13441debfc3dSmrg be traversed. */
13451debfc3dSmrg }
13461debfc3dSmrg
13471debfc3dSmrg
13481debfc3dSmrg /* PCH support for vec<T, A, vl_embed>. */
13491debfc3dSmrg
13501debfc3dSmrg template<typename T, typename A>
13511debfc3dSmrg void
13521debfc3dSmrg gt_pch_nx (vec<T, A, vl_embed> *v)
13531debfc3dSmrg {
13541debfc3dSmrg extern void gt_pch_nx (T &);
13551debfc3dSmrg for (unsigned i = 0; i < v->length (); i++)
13561debfc3dSmrg gt_pch_nx ((*v)[i]);
13571debfc3dSmrg }
13581debfc3dSmrg
13591debfc3dSmrg template<typename T, typename A>
13601debfc3dSmrg void
13611debfc3dSmrg gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
13621debfc3dSmrg {
13631debfc3dSmrg for (unsigned i = 0; i < v->length (); i++)
13641debfc3dSmrg op (&((*v)[i]), cookie);
13651debfc3dSmrg }
13661debfc3dSmrg
13671debfc3dSmrg template<typename T, typename A>
13681debfc3dSmrg void
13691debfc3dSmrg gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
13701debfc3dSmrg {
13711debfc3dSmrg extern void gt_pch_nx (T *, gt_pointer_operator, void *);
13721debfc3dSmrg for (unsigned i = 0; i < v->length (); i++)
13731debfc3dSmrg gt_pch_nx (&((*v)[i]), op, cookie);
13741debfc3dSmrg }
13751debfc3dSmrg
13761debfc3dSmrg
13771debfc3dSmrg /* Space efficient vector. These vectors can grow dynamically and are
13781debfc3dSmrg allocated together with their control data. They are suited to be
13791debfc3dSmrg included in data structures. Prior to initial allocation, they
13801debfc3dSmrg only take a single word of storage.
13811debfc3dSmrg
13821debfc3dSmrg These vectors are implemented as a pointer to an embeddable vector.
13831debfc3dSmrg The semantics allow for this pointer to be NULL to represent empty
13841debfc3dSmrg vectors. This way, empty vectors occupy minimal space in the
13851debfc3dSmrg structure containing them.
13861debfc3dSmrg
13871debfc3dSmrg Properties:
13881debfc3dSmrg
13891debfc3dSmrg - The whole vector and control data are allocated in a single
13901debfc3dSmrg contiguous block.
13911debfc3dSmrg - The whole vector may be re-allocated.
13921debfc3dSmrg - Vector data may grow and shrink.
13931debfc3dSmrg - Access and manipulation requires a pointer test and
13941debfc3dSmrg indirection.
13951debfc3dSmrg - It requires 1 word of storage (prior to vector allocation).
13961debfc3dSmrg
13971debfc3dSmrg
13981debfc3dSmrg Limitations:
13991debfc3dSmrg
14001debfc3dSmrg These vectors must be PODs because they are stored in unions.
14011debfc3dSmrg (http://en.wikipedia.org/wiki/Plain_old_data_structures).
14021debfc3dSmrg As long as we use C++03, we cannot have constructors nor
14031debfc3dSmrg destructors in classes that are stored in unions. */
14041debfc3dSmrg
14051debfc3dSmrg template<typename T>
14061debfc3dSmrg struct vec<T, va_heap, vl_ptr>
14071debfc3dSmrg {
14081debfc3dSmrg public:
14091debfc3dSmrg /* Memory allocation and deallocation for the embedded vector.
14101debfc3dSmrg Needed because we cannot have proper ctors/dtors defined. */
14111debfc3dSmrg void create (unsigned nelems CXX_MEM_STAT_INFO);
14121debfc3dSmrg void release (void);
14131debfc3dSmrg
14141debfc3dSmrg /* Vector operations. */
14151debfc3dSmrg bool exists (void) const
14161debfc3dSmrg { return m_vec != NULL; }
14171debfc3dSmrg
14181debfc3dSmrg bool is_empty (void) const
14191debfc3dSmrg { return m_vec ? m_vec->is_empty () : true; }
14201debfc3dSmrg
14211debfc3dSmrg unsigned length (void) const
14221debfc3dSmrg { return m_vec ? m_vec->length () : 0; }
14231debfc3dSmrg
14241debfc3dSmrg T *address (void)
14251debfc3dSmrg { return m_vec ? m_vec->m_vecdata : NULL; }
14261debfc3dSmrg
14271debfc3dSmrg const T *address (void) const
14281debfc3dSmrg { return m_vec ? m_vec->m_vecdata : NULL; }
14291debfc3dSmrg
14301debfc3dSmrg T *begin () { return address (); }
14311debfc3dSmrg const T *begin () const { return address (); }
14321debfc3dSmrg T *end () { return begin () + length (); }
14331debfc3dSmrg const T *end () const { return begin () + length (); }
14341debfc3dSmrg const T &operator[] (unsigned ix) const
14351debfc3dSmrg { return (*m_vec)[ix]; }
14361debfc3dSmrg
14371debfc3dSmrg bool operator!=(const vec &other) const
14381debfc3dSmrg { return !(*this == other); }
14391debfc3dSmrg
14401debfc3dSmrg bool operator==(const vec &other) const
14411debfc3dSmrg { return address () == other.address (); }
14421debfc3dSmrg
14431debfc3dSmrg T &operator[] (unsigned ix)
14441debfc3dSmrg { return (*m_vec)[ix]; }
14451debfc3dSmrg
14461debfc3dSmrg T &last (void)
14471debfc3dSmrg { return m_vec->last (); }
14481debfc3dSmrg
14491debfc3dSmrg bool space (int nelems) const
14501debfc3dSmrg { return m_vec ? m_vec->space (nelems) : nelems == 0; }
14511debfc3dSmrg
14521debfc3dSmrg bool iterate (unsigned ix, T *p) const;
14531debfc3dSmrg bool iterate (unsigned ix, T **p) const;
14541debfc3dSmrg vec copy (ALONE_CXX_MEM_STAT_INFO) const;
14551debfc3dSmrg bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
14561debfc3dSmrg bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
14571debfc3dSmrg void splice (const vec &);
14581debfc3dSmrg void safe_splice (const vec & CXX_MEM_STAT_INFO);
14591debfc3dSmrg T *quick_push (const T &);
14601debfc3dSmrg T *safe_push (const T &CXX_MEM_STAT_INFO);
14611debfc3dSmrg T &pop (void);
14621debfc3dSmrg void truncate (unsigned);
14631debfc3dSmrg void safe_grow (unsigned CXX_MEM_STAT_INFO);
14641debfc3dSmrg void safe_grow_cleared (unsigned CXX_MEM_STAT_INFO);
14651debfc3dSmrg void quick_grow (unsigned);
14661debfc3dSmrg void quick_grow_cleared (unsigned);
14671debfc3dSmrg void quick_insert (unsigned, const T &);
14681debfc3dSmrg void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
14691debfc3dSmrg void ordered_remove (unsigned);
14701debfc3dSmrg void unordered_remove (unsigned);
14711debfc3dSmrg void block_remove (unsigned, unsigned);
14721debfc3dSmrg void qsort (int (*) (const void *, const void *));
1473*8feb0f0bSmrg void sort (int (*) (const void *, const void *, void *), void *);
14741debfc3dSmrg T *bsearch (const void *key, int (*compar)(const void *, const void *));
1475*8feb0f0bSmrg T *bsearch (const void *key,
1476*8feb0f0bSmrg int (*compar)(const void *, const void *, void *), void *);
14771debfc3dSmrg unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
14781debfc3dSmrg bool contains (const T &search) const;
1479c0a68be4Smrg void reverse (void);
14801debfc3dSmrg
14811debfc3dSmrg bool using_auto_storage () const;
14821debfc3dSmrg
14831debfc3dSmrg /* FIXME - This field should be private, but we need to cater to
14841debfc3dSmrg compilers that have stricter notions of PODness for types. */
14851debfc3dSmrg vec<T, va_heap, vl_embed> *m_vec;
14861debfc3dSmrg };
14871debfc3dSmrg
14881debfc3dSmrg
14891debfc3dSmrg /* auto_vec is a subclass of vec that automatically manages creating and
14901debfc3dSmrg releasing the internal vector. If N is non zero then it has N elements of
14911debfc3dSmrg internal storage. The default is no internal storage, and you probably only
14921debfc3dSmrg want to ask for internal storage for vectors on the stack because if the
14931debfc3dSmrg size of the vector is larger than the internal storage that space is wasted.
14941debfc3dSmrg */
14951debfc3dSmrg template<typename T, size_t N = 0>
14961debfc3dSmrg class auto_vec : public vec<T, va_heap>
14971debfc3dSmrg {
14981debfc3dSmrg public:
14991debfc3dSmrg auto_vec ()
15001debfc3dSmrg {
15011debfc3dSmrg m_auto.embedded_init (MAX (N, 2), 0, 1);
15021debfc3dSmrg this->m_vec = &m_auto;
15031debfc3dSmrg }
15041debfc3dSmrg
1505a2dc1f3fSmrg auto_vec (size_t s)
1506a2dc1f3fSmrg {
1507a2dc1f3fSmrg if (s > N)
1508a2dc1f3fSmrg {
1509a2dc1f3fSmrg this->create (s);
1510a2dc1f3fSmrg return;
1511a2dc1f3fSmrg }
1512a2dc1f3fSmrg
1513a2dc1f3fSmrg m_auto.embedded_init (MAX (N, 2), 0, 1);
1514a2dc1f3fSmrg this->m_vec = &m_auto;
1515a2dc1f3fSmrg }
1516a2dc1f3fSmrg
15171debfc3dSmrg ~auto_vec ()
15181debfc3dSmrg {
15191debfc3dSmrg this->release ();
15201debfc3dSmrg }
15211debfc3dSmrg
15221debfc3dSmrg private:
15231debfc3dSmrg vec<T, va_heap, vl_embed> m_auto;
15241debfc3dSmrg T m_data[MAX (N - 1, 1)];
15251debfc3dSmrg };
15261debfc3dSmrg
15271debfc3dSmrg /* auto_vec is a sub class of vec whose storage is released when it is
15281debfc3dSmrg destroyed. */
15291debfc3dSmrg template<typename T>
15301debfc3dSmrg class auto_vec<T, 0> : public vec<T, va_heap>
15311debfc3dSmrg {
15321debfc3dSmrg public:
15331debfc3dSmrg auto_vec () { this->m_vec = NULL; }
15341debfc3dSmrg auto_vec (size_t n) { this->create (n); }
15351debfc3dSmrg ~auto_vec () { this->release (); }
15361debfc3dSmrg };
15371debfc3dSmrg
15381debfc3dSmrg
15391debfc3dSmrg /* Allocate heap memory for pointer V and create the internal vector
15401debfc3dSmrg with space for NELEMS elements. If NELEMS is 0, the internal
15411debfc3dSmrg vector is initialized to empty. */
15421debfc3dSmrg
15431debfc3dSmrg template<typename T>
15441debfc3dSmrg inline void
15451debfc3dSmrg vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
15461debfc3dSmrg {
15471debfc3dSmrg v = new vec<T>;
15481debfc3dSmrg v->create (nelems PASS_MEM_STAT);
15491debfc3dSmrg }
15501debfc3dSmrg
15511debfc3dSmrg
1552c0a68be4Smrg /* A subclass of auto_vec <char *> that frees all of its elements on
1553c0a68be4Smrg deletion. */
1554c0a68be4Smrg
1555c0a68be4Smrg class auto_string_vec : public auto_vec <char *>
1556c0a68be4Smrg {
1557c0a68be4Smrg public:
1558c0a68be4Smrg ~auto_string_vec ();
1559c0a68be4Smrg };
1560c0a68be4Smrg
1561*8feb0f0bSmrg /* A subclass of auto_vec <T *> that deletes all of its elements on
1562*8feb0f0bSmrg destruction.
1563*8feb0f0bSmrg
1564*8feb0f0bSmrg This is a crude way for a vec to "own" the objects it points to
1565*8feb0f0bSmrg and clean up automatically.
1566*8feb0f0bSmrg
1567*8feb0f0bSmrg For example, no attempt is made to delete elements when an item
1568*8feb0f0bSmrg within the vec is overwritten.
1569*8feb0f0bSmrg
1570*8feb0f0bSmrg We can't rely on gnu::unique_ptr within a container,
1571*8feb0f0bSmrg since we can't rely on move semantics in C++98. */
1572*8feb0f0bSmrg
1573*8feb0f0bSmrg template <typename T>
1574*8feb0f0bSmrg class auto_delete_vec : public auto_vec <T *>
1575*8feb0f0bSmrg {
1576*8feb0f0bSmrg public:
1577*8feb0f0bSmrg auto_delete_vec () {}
1578*8feb0f0bSmrg auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
1579*8feb0f0bSmrg
1580*8feb0f0bSmrg ~auto_delete_vec ();
1581*8feb0f0bSmrg
1582*8feb0f0bSmrg private:
1583*8feb0f0bSmrg DISABLE_COPY_AND_ASSIGN(auto_delete_vec);
1584*8feb0f0bSmrg };
1585*8feb0f0bSmrg
15861debfc3dSmrg /* Conditionally allocate heap memory for VEC and its internal vector. */
15871debfc3dSmrg
15881debfc3dSmrg template<typename T>
15891debfc3dSmrg inline void
15901debfc3dSmrg vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
15911debfc3dSmrg {
15921debfc3dSmrg if (!vec)
15931debfc3dSmrg vec_alloc (vec, nelems PASS_MEM_STAT);
15941debfc3dSmrg }
15951debfc3dSmrg
15961debfc3dSmrg
15971debfc3dSmrg /* Free the heap memory allocated by vector V and set it to NULL. */
15981debfc3dSmrg
15991debfc3dSmrg template<typename T>
16001debfc3dSmrg inline void
16011debfc3dSmrg vec_free (vec<T> *&v)
16021debfc3dSmrg {
16031debfc3dSmrg if (v == NULL)
16041debfc3dSmrg return;
16051debfc3dSmrg
16061debfc3dSmrg v->release ();
16071debfc3dSmrg delete v;
16081debfc3dSmrg v = NULL;
16091debfc3dSmrg }
16101debfc3dSmrg
16111debfc3dSmrg
16121debfc3dSmrg /* Return iteration condition and update PTR to point to the IX'th
16131debfc3dSmrg element of this vector. Use this to iterate over the elements of a
16141debfc3dSmrg vector as follows,
16151debfc3dSmrg
16161debfc3dSmrg for (ix = 0; v.iterate (ix, &ptr); ix++)
16171debfc3dSmrg continue; */
16181debfc3dSmrg
16191debfc3dSmrg template<typename T>
16201debfc3dSmrg inline bool
16211debfc3dSmrg vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
16221debfc3dSmrg {
16231debfc3dSmrg if (m_vec)
16241debfc3dSmrg return m_vec->iterate (ix, ptr);
16251debfc3dSmrg else
16261debfc3dSmrg {
16271debfc3dSmrg *ptr = 0;
16281debfc3dSmrg return false;
16291debfc3dSmrg }
16301debfc3dSmrg }
16311debfc3dSmrg
16321debfc3dSmrg
16331debfc3dSmrg /* Return iteration condition and update *PTR to point to the
16341debfc3dSmrg IX'th element of this vector. Use this to iterate over the
16351debfc3dSmrg elements of a vector as follows,
16361debfc3dSmrg
16371debfc3dSmrg for (ix = 0; v->iterate (ix, &ptr); ix++)
16381debfc3dSmrg continue;
16391debfc3dSmrg
16401debfc3dSmrg This variant is for vectors of objects. */
16411debfc3dSmrg
16421debfc3dSmrg template<typename T>
16431debfc3dSmrg inline bool
16441debfc3dSmrg vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
16451debfc3dSmrg {
16461debfc3dSmrg if (m_vec)
16471debfc3dSmrg return m_vec->iterate (ix, ptr);
16481debfc3dSmrg else
16491debfc3dSmrg {
16501debfc3dSmrg *ptr = 0;
16511debfc3dSmrg return false;
16521debfc3dSmrg }
16531debfc3dSmrg }
16541debfc3dSmrg
16551debfc3dSmrg
16561debfc3dSmrg /* Convenience macro for forward iteration. */
16571debfc3dSmrg #define FOR_EACH_VEC_ELT(V, I, P) \
16581debfc3dSmrg for (I = 0; (V).iterate ((I), &(P)); ++(I))
16591debfc3dSmrg
16601debfc3dSmrg #define FOR_EACH_VEC_SAFE_ELT(V, I, P) \
16611debfc3dSmrg for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
16621debfc3dSmrg
16631debfc3dSmrg /* Likewise, but start from FROM rather than 0. */
16641debfc3dSmrg #define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM) \
16651debfc3dSmrg for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
16661debfc3dSmrg
16671debfc3dSmrg /* Convenience macro for reverse iteration. */
16681debfc3dSmrg #define FOR_EACH_VEC_ELT_REVERSE(V, I, P) \
16691debfc3dSmrg for (I = (V).length () - 1; \
16701debfc3dSmrg (V).iterate ((I), &(P)); \
16711debfc3dSmrg (I)--)
16721debfc3dSmrg
16731debfc3dSmrg #define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P) \
16741debfc3dSmrg for (I = vec_safe_length (V) - 1; \
16751debfc3dSmrg vec_safe_iterate ((V), (I), &(P)); \
16761debfc3dSmrg (I)--)
16771debfc3dSmrg
1678c0a68be4Smrg /* auto_string_vec's dtor, freeing all contained strings, automatically
1679c0a68be4Smrg chaining up to ~auto_vec <char *>, which frees the internal buffer. */
1680c0a68be4Smrg
1681c0a68be4Smrg inline
1682c0a68be4Smrg auto_string_vec::~auto_string_vec ()
1683c0a68be4Smrg {
1684c0a68be4Smrg int i;
1685c0a68be4Smrg char *str;
1686c0a68be4Smrg FOR_EACH_VEC_ELT (*this, i, str)
1687c0a68be4Smrg free (str);
1688c0a68be4Smrg }
1689c0a68be4Smrg
1690*8feb0f0bSmrg /* auto_delete_vec's dtor, deleting all contained items, automatically
1691*8feb0f0bSmrg chaining up to ~auto_vec <T*>, which frees the internal buffer. */
1692*8feb0f0bSmrg
1693*8feb0f0bSmrg template <typename T>
1694*8feb0f0bSmrg inline
1695*8feb0f0bSmrg auto_delete_vec<T>::~auto_delete_vec ()
1696*8feb0f0bSmrg {
1697*8feb0f0bSmrg int i;
1698*8feb0f0bSmrg T *item;
1699*8feb0f0bSmrg FOR_EACH_VEC_ELT (*this, i, item)
1700*8feb0f0bSmrg delete item;
1701*8feb0f0bSmrg }
1702*8feb0f0bSmrg
17031debfc3dSmrg
17041debfc3dSmrg /* Return a copy of this vector. */
17051debfc3dSmrg
17061debfc3dSmrg template<typename T>
17071debfc3dSmrg inline vec<T, va_heap, vl_ptr>
17081debfc3dSmrg vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
17091debfc3dSmrg {
17101debfc3dSmrg vec<T, va_heap, vl_ptr> new_vec = vNULL;
17111debfc3dSmrg if (length ())
17121debfc3dSmrg new_vec.m_vec = m_vec->copy ();
17131debfc3dSmrg return new_vec;
17141debfc3dSmrg }
17151debfc3dSmrg
17161debfc3dSmrg
17171debfc3dSmrg /* Ensure that the vector has at least RESERVE slots available (if
17181debfc3dSmrg EXACT is false), or exactly RESERVE slots available (if EXACT is
17191debfc3dSmrg true).
17201debfc3dSmrg
17211debfc3dSmrg This may create additional headroom if EXACT is false.
17221debfc3dSmrg
17231debfc3dSmrg Note that this can cause the embedded vector to be reallocated.
17241debfc3dSmrg Returns true iff reallocation actually occurred. */
17251debfc3dSmrg
17261debfc3dSmrg template<typename T>
17271debfc3dSmrg inline bool
17281debfc3dSmrg vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
17291debfc3dSmrg {
17301debfc3dSmrg if (space (nelems))
17311debfc3dSmrg return false;
17321debfc3dSmrg
17331debfc3dSmrg /* For now play a game with va_heap::reserve to hide our auto storage if any,
17341debfc3dSmrg this is necessary because it doesn't have enough information to know the
17351debfc3dSmrg embedded vector is in auto storage, and so should not be freed. */
17361debfc3dSmrg vec<T, va_heap, vl_embed> *oldvec = m_vec;
17371debfc3dSmrg unsigned int oldsize = 0;
17381debfc3dSmrg bool handle_auto_vec = m_vec && using_auto_storage ();
17391debfc3dSmrg if (handle_auto_vec)
17401debfc3dSmrg {
17411debfc3dSmrg m_vec = NULL;
17421debfc3dSmrg oldsize = oldvec->length ();
17431debfc3dSmrg nelems += oldsize;
17441debfc3dSmrg }
17451debfc3dSmrg
17461debfc3dSmrg va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
17471debfc3dSmrg if (handle_auto_vec)
17481debfc3dSmrg {
1749a2dc1f3fSmrg vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
17501debfc3dSmrg m_vec->m_vecpfx.m_num = oldsize;
17511debfc3dSmrg }
17521debfc3dSmrg
17531debfc3dSmrg return true;
17541debfc3dSmrg }
17551debfc3dSmrg
17561debfc3dSmrg
17571debfc3dSmrg /* Ensure that this vector has exactly NELEMS slots available. This
17581debfc3dSmrg will not create additional headroom. Note this can cause the
17591debfc3dSmrg embedded vector to be reallocated. Returns true iff reallocation
17601debfc3dSmrg actually occurred. */
17611debfc3dSmrg
17621debfc3dSmrg template<typename T>
17631debfc3dSmrg inline bool
17641debfc3dSmrg vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
17651debfc3dSmrg {
17661debfc3dSmrg return reserve (nelems, true PASS_MEM_STAT);
17671debfc3dSmrg }
17681debfc3dSmrg
17691debfc3dSmrg
17701debfc3dSmrg /* Create the internal vector and reserve NELEMS for it. This is
17711debfc3dSmrg exactly like vec::reserve, but the internal vector is
17721debfc3dSmrg unconditionally allocated from scratch. The old one, if it
17731debfc3dSmrg existed, is lost. */
17741debfc3dSmrg
17751debfc3dSmrg template<typename T>
17761debfc3dSmrg inline void
17771debfc3dSmrg vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
17781debfc3dSmrg {
17791debfc3dSmrg m_vec = NULL;
17801debfc3dSmrg if (nelems > 0)
17811debfc3dSmrg reserve_exact (nelems PASS_MEM_STAT);
17821debfc3dSmrg }
17831debfc3dSmrg
17841debfc3dSmrg
17851debfc3dSmrg /* Free the memory occupied by the embedded vector. */
17861debfc3dSmrg
17871debfc3dSmrg template<typename T>
17881debfc3dSmrg inline void
17891debfc3dSmrg vec<T, va_heap, vl_ptr>::release (void)
17901debfc3dSmrg {
17911debfc3dSmrg if (!m_vec)
17921debfc3dSmrg return;
17931debfc3dSmrg
17941debfc3dSmrg if (using_auto_storage ())
17951debfc3dSmrg {
17961debfc3dSmrg m_vec->m_vecpfx.m_num = 0;
17971debfc3dSmrg return;
17981debfc3dSmrg }
17991debfc3dSmrg
18001debfc3dSmrg va_heap::release (m_vec);
18011debfc3dSmrg }
18021debfc3dSmrg
18031debfc3dSmrg /* Copy the elements from SRC to the end of this vector as if by memcpy.
18041debfc3dSmrg SRC and this vector must be allocated with the same memory
18051debfc3dSmrg allocation mechanism. This vector is assumed to have sufficient
18061debfc3dSmrg headroom available. */
18071debfc3dSmrg
18081debfc3dSmrg template<typename T>
18091debfc3dSmrg inline void
18101debfc3dSmrg vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
18111debfc3dSmrg {
1812c0a68be4Smrg if (src.length ())
18131debfc3dSmrg m_vec->splice (*(src.m_vec));
18141debfc3dSmrg }
18151debfc3dSmrg
18161debfc3dSmrg
18171debfc3dSmrg /* Copy the elements in SRC to the end of this vector as if by memcpy.
18181debfc3dSmrg SRC and this vector must be allocated with the same mechanism.
18191debfc3dSmrg If there is not enough headroom in this vector, it will be reallocated
18201debfc3dSmrg as needed. */
18211debfc3dSmrg
18221debfc3dSmrg template<typename T>
18231debfc3dSmrg inline void
18241debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
18251debfc3dSmrg MEM_STAT_DECL)
18261debfc3dSmrg {
18271debfc3dSmrg if (src.length ())
18281debfc3dSmrg {
18291debfc3dSmrg reserve_exact (src.length ());
18301debfc3dSmrg splice (src);
18311debfc3dSmrg }
18321debfc3dSmrg }
18331debfc3dSmrg
18341debfc3dSmrg
18351debfc3dSmrg /* Push OBJ (a new element) onto the end of the vector. There must be
18361debfc3dSmrg sufficient space in the vector. Return a pointer to the slot
18371debfc3dSmrg where OBJ was inserted. */
18381debfc3dSmrg
18391debfc3dSmrg template<typename T>
18401debfc3dSmrg inline T *
18411debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
18421debfc3dSmrg {
18431debfc3dSmrg return m_vec->quick_push (obj);
18441debfc3dSmrg }
18451debfc3dSmrg
18461debfc3dSmrg
18471debfc3dSmrg /* Push a new element OBJ onto the end of this vector. Reallocates
18481debfc3dSmrg the embedded vector, if needed. Return a pointer to the slot where
18491debfc3dSmrg OBJ was inserted. */
18501debfc3dSmrg
18511debfc3dSmrg template<typename T>
18521debfc3dSmrg inline T *
18531debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
18541debfc3dSmrg {
18551debfc3dSmrg reserve (1, false PASS_MEM_STAT);
18561debfc3dSmrg return quick_push (obj);
18571debfc3dSmrg }
18581debfc3dSmrg
18591debfc3dSmrg
18601debfc3dSmrg /* Pop and return the last element off the end of the vector. */
18611debfc3dSmrg
18621debfc3dSmrg template<typename T>
18631debfc3dSmrg inline T &
18641debfc3dSmrg vec<T, va_heap, vl_ptr>::pop (void)
18651debfc3dSmrg {
18661debfc3dSmrg return m_vec->pop ();
18671debfc3dSmrg }
18681debfc3dSmrg
18691debfc3dSmrg
18701debfc3dSmrg /* Set the length of the vector to LEN. The new length must be less
18711debfc3dSmrg than or equal to the current length. This is an O(1) operation. */
18721debfc3dSmrg
18731debfc3dSmrg template<typename T>
18741debfc3dSmrg inline void
18751debfc3dSmrg vec<T, va_heap, vl_ptr>::truncate (unsigned size)
18761debfc3dSmrg {
18771debfc3dSmrg if (m_vec)
18781debfc3dSmrg m_vec->truncate (size);
18791debfc3dSmrg else
18801debfc3dSmrg gcc_checking_assert (size == 0);
18811debfc3dSmrg }
18821debfc3dSmrg
18831debfc3dSmrg
18841debfc3dSmrg /* Grow the vector to a specific length. LEN must be as long or
18851debfc3dSmrg longer than the current length. The new elements are
18861debfc3dSmrg uninitialized. Reallocate the internal vector, if needed. */
18871debfc3dSmrg
18881debfc3dSmrg template<typename T>
18891debfc3dSmrg inline void
18901debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL)
18911debfc3dSmrg {
18921debfc3dSmrg unsigned oldlen = length ();
18931debfc3dSmrg gcc_checking_assert (oldlen <= len);
18941debfc3dSmrg reserve_exact (len - oldlen PASS_MEM_STAT);
18951debfc3dSmrg if (m_vec)
18961debfc3dSmrg m_vec->quick_grow (len);
18971debfc3dSmrg else
18981debfc3dSmrg gcc_checking_assert (len == 0);
18991debfc3dSmrg }
19001debfc3dSmrg
19011debfc3dSmrg
19021debfc3dSmrg /* Grow the embedded vector to a specific length. LEN must be as
19031debfc3dSmrg long or longer than the current length. The new elements are
19041debfc3dSmrg initialized to zero. Reallocate the internal vector, if needed. */
19051debfc3dSmrg
19061debfc3dSmrg template<typename T>
19071debfc3dSmrg inline void
19081debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL)
19091debfc3dSmrg {
19101debfc3dSmrg unsigned oldlen = length ();
1911a2dc1f3fSmrg size_t growby = len - oldlen;
19121debfc3dSmrg safe_grow (len PASS_MEM_STAT);
1913a2dc1f3fSmrg if (growby != 0)
1914a2dc1f3fSmrg vec_default_construct (address () + oldlen, growby);
19151debfc3dSmrg }
19161debfc3dSmrg
19171debfc3dSmrg
19181debfc3dSmrg /* Same as vec::safe_grow but without reallocation of the internal vector.
19191debfc3dSmrg If the vector cannot be extended, a runtime assertion will be triggered. */
19201debfc3dSmrg
19211debfc3dSmrg template<typename T>
19221debfc3dSmrg inline void
19231debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
19241debfc3dSmrg {
19251debfc3dSmrg gcc_checking_assert (m_vec);
19261debfc3dSmrg m_vec->quick_grow (len);
19271debfc3dSmrg }
19281debfc3dSmrg
19291debfc3dSmrg
19301debfc3dSmrg /* Same as vec::quick_grow_cleared but without reallocation of the
19311debfc3dSmrg internal vector. If the vector cannot be extended, a runtime
19321debfc3dSmrg assertion will be triggered. */
19331debfc3dSmrg
19341debfc3dSmrg template<typename T>
19351debfc3dSmrg inline void
19361debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
19371debfc3dSmrg {
19381debfc3dSmrg gcc_checking_assert (m_vec);
19391debfc3dSmrg m_vec->quick_grow_cleared (len);
19401debfc3dSmrg }
19411debfc3dSmrg
19421debfc3dSmrg
19431debfc3dSmrg /* Insert an element, OBJ, at the IXth position of this vector. There
19441debfc3dSmrg must be sufficient space. */
19451debfc3dSmrg
19461debfc3dSmrg template<typename T>
19471debfc3dSmrg inline void
19481debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
19491debfc3dSmrg {
19501debfc3dSmrg m_vec->quick_insert (ix, obj);
19511debfc3dSmrg }
19521debfc3dSmrg
19531debfc3dSmrg
19541debfc3dSmrg /* Insert an element, OBJ, at the IXth position of the vector.
19551debfc3dSmrg Reallocate the embedded vector, if necessary. */
19561debfc3dSmrg
19571debfc3dSmrg template<typename T>
19581debfc3dSmrg inline void
19591debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
19601debfc3dSmrg {
19611debfc3dSmrg reserve (1, false PASS_MEM_STAT);
19621debfc3dSmrg quick_insert (ix, obj);
19631debfc3dSmrg }
19641debfc3dSmrg
19651debfc3dSmrg
19661debfc3dSmrg /* Remove an element from the IXth position of this vector. Ordering of
19671debfc3dSmrg remaining elements is preserved. This is an O(N) operation due to
19681debfc3dSmrg a memmove. */
19691debfc3dSmrg
19701debfc3dSmrg template<typename T>
19711debfc3dSmrg inline void
19721debfc3dSmrg vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
19731debfc3dSmrg {
19741debfc3dSmrg m_vec->ordered_remove (ix);
19751debfc3dSmrg }
19761debfc3dSmrg
19771debfc3dSmrg
19781debfc3dSmrg /* Remove an element from the IXth position of this vector. Ordering
19791debfc3dSmrg of remaining elements is destroyed. This is an O(1) operation. */
19801debfc3dSmrg
19811debfc3dSmrg template<typename T>
19821debfc3dSmrg inline void
19831debfc3dSmrg vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
19841debfc3dSmrg {
19851debfc3dSmrg m_vec->unordered_remove (ix);
19861debfc3dSmrg }
19871debfc3dSmrg
19881debfc3dSmrg
19891debfc3dSmrg /* Remove LEN elements starting at the IXth. Ordering is retained.
19901debfc3dSmrg This is an O(N) operation due to memmove. */
19911debfc3dSmrg
19921debfc3dSmrg template<typename T>
19931debfc3dSmrg inline void
19941debfc3dSmrg vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
19951debfc3dSmrg {
19961debfc3dSmrg m_vec->block_remove (ix, len);
19971debfc3dSmrg }
19981debfc3dSmrg
19991debfc3dSmrg
20001debfc3dSmrg /* Sort the contents of this vector with qsort. CMP is the comparison
20011debfc3dSmrg function to pass to qsort. */
20021debfc3dSmrg
20031debfc3dSmrg template<typename T>
20041debfc3dSmrg inline void
20051debfc3dSmrg vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
20061debfc3dSmrg {
20071debfc3dSmrg if (m_vec)
20081debfc3dSmrg m_vec->qsort (cmp);
20091debfc3dSmrg }
20101debfc3dSmrg
2011*8feb0f0bSmrg /* Sort the contents of this vector with qsort. CMP is the comparison
2012*8feb0f0bSmrg function to pass to qsort. */
2013*8feb0f0bSmrg
2014*8feb0f0bSmrg template<typename T>
2015*8feb0f0bSmrg inline void
2016*8feb0f0bSmrg vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *,
2017*8feb0f0bSmrg void *), void *data)
2018*8feb0f0bSmrg {
2019*8feb0f0bSmrg if (m_vec)
2020*8feb0f0bSmrg m_vec->sort (cmp, data);
2021*8feb0f0bSmrg }
2022*8feb0f0bSmrg
20231debfc3dSmrg
20241debfc3dSmrg /* Search the contents of the sorted vector with a binary search.
20251debfc3dSmrg CMP is the comparison function to pass to bsearch. */
20261debfc3dSmrg
20271debfc3dSmrg template<typename T>
20281debfc3dSmrg inline T *
20291debfc3dSmrg vec<T, va_heap, vl_ptr>::bsearch (const void *key,
20301debfc3dSmrg int (*cmp) (const void *, const void *))
20311debfc3dSmrg {
20321debfc3dSmrg if (m_vec)
20331debfc3dSmrg return m_vec->bsearch (key, cmp);
20341debfc3dSmrg return NULL;
20351debfc3dSmrg }
20361debfc3dSmrg
2037*8feb0f0bSmrg /* Search the contents of the sorted vector with a binary search.
2038*8feb0f0bSmrg CMP is the comparison function to pass to bsearch. */
2039*8feb0f0bSmrg
2040*8feb0f0bSmrg template<typename T>
2041*8feb0f0bSmrg inline T *
2042*8feb0f0bSmrg vec<T, va_heap, vl_ptr>::bsearch (const void *key,
2043*8feb0f0bSmrg int (*cmp) (const void *, const void *,
2044*8feb0f0bSmrg void *), void *data)
2045*8feb0f0bSmrg {
2046*8feb0f0bSmrg if (m_vec)
2047*8feb0f0bSmrg return m_vec->bsearch (key, cmp, data);
2048*8feb0f0bSmrg return NULL;
2049*8feb0f0bSmrg }
2050*8feb0f0bSmrg
20511debfc3dSmrg
20521debfc3dSmrg /* Find and return the first position in which OBJ could be inserted
20531debfc3dSmrg without changing the ordering of this vector. LESSTHAN is a
20541debfc3dSmrg function that returns true if the first argument is strictly less
20551debfc3dSmrg than the second. */
20561debfc3dSmrg
20571debfc3dSmrg template<typename T>
20581debfc3dSmrg inline unsigned
20591debfc3dSmrg vec<T, va_heap, vl_ptr>::lower_bound (T obj,
20601debfc3dSmrg bool (*lessthan)(const T &, const T &))
20611debfc3dSmrg const
20621debfc3dSmrg {
20631debfc3dSmrg return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
20641debfc3dSmrg }
20651debfc3dSmrg
20661debfc3dSmrg /* Return true if SEARCH is an element of V. Note that this is O(N) in the
20671debfc3dSmrg size of the vector and so should be used with care. */
20681debfc3dSmrg
20691debfc3dSmrg template<typename T>
20701debfc3dSmrg inline bool
20711debfc3dSmrg vec<T, va_heap, vl_ptr>::contains (const T &search) const
20721debfc3dSmrg {
20731debfc3dSmrg return m_vec ? m_vec->contains (search) : false;
20741debfc3dSmrg }
20751debfc3dSmrg
2076c0a68be4Smrg /* Reverse content of the vector. */
2077c0a68be4Smrg
2078c0a68be4Smrg template<typename T>
2079c0a68be4Smrg inline void
2080c0a68be4Smrg vec<T, va_heap, vl_ptr>::reverse (void)
2081c0a68be4Smrg {
2082c0a68be4Smrg unsigned l = length ();
2083c0a68be4Smrg T *ptr = address ();
2084c0a68be4Smrg
2085c0a68be4Smrg for (unsigned i = 0; i < l / 2; i++)
2086c0a68be4Smrg std::swap (ptr[i], ptr[l - i - 1]);
2087c0a68be4Smrg }
2088c0a68be4Smrg
20891debfc3dSmrg template<typename T>
20901debfc3dSmrg inline bool
20911debfc3dSmrg vec<T, va_heap, vl_ptr>::using_auto_storage () const
20921debfc3dSmrg {
20931debfc3dSmrg return m_vec->m_vecpfx.m_using_auto_storage;
20941debfc3dSmrg }
20951debfc3dSmrg
20961debfc3dSmrg /* Release VEC and call release of all element vectors. */
20971debfc3dSmrg
20981debfc3dSmrg template<typename T>
20991debfc3dSmrg inline void
21001debfc3dSmrg release_vec_vec (vec<vec<T> > &vec)
21011debfc3dSmrg {
21021debfc3dSmrg for (unsigned i = 0; i < vec.length (); i++)
21031debfc3dSmrg vec[i].release ();
21041debfc3dSmrg
21051debfc3dSmrg vec.release ();
21061debfc3dSmrg }
21071debfc3dSmrg
21081debfc3dSmrg #if (GCC_VERSION >= 3000)
21091debfc3dSmrg # pragma GCC poison m_vec m_vecpfx m_vecdata
21101debfc3dSmrg #endif
21111debfc3dSmrg
21121debfc3dSmrg #endif // GCC_VEC_H
2113