2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #ifndef included_vec_h
39 #define included_vec_h
41 #include <vppinfra/clib.h> /* word, etc */
42 #include <vppinfra/mem.h> /* clib_mem_free */
43 #include <vppinfra/string.h> /* memcpy, memmove */
44 #include <vppinfra/vec_bootstrap.h>
48 CLIB vectors are ubiquitous dynamically resized arrays with by user
49 defined "headers". Many CLIB data structures (e.g. hash, heap,
50 pool) are vectors with various different headers.
52 The memory layout looks like this:
55 user header (start of memory allocation)
57 heap pointer (optional, only if default_heap == 0)
58 vector header: number of elements, header size
59 user's pointer-> vector element #0
64 The user pointer contains the address of vector element # 0. Null
65 pointer vectors are valid and mean a zero length vector.
67 You can reset the length of an allocated vector to zero via the
68 vec_reset_length(v) macro, or by setting the vector length field to
69 zero (e.g. _vec_len (v) = 0). Vec_reset_length(v) preferred: it
70 understands Null pointers.
72 Typically, the header is not present. Headers allow for other
73 data structures to be built atop CLIB vectors.
75 While users may specify the alignment for first data element of a vector
76 via the vec_*_aligned macros that is typically not needed as alignment
77 is set based on native alignment of the data structure used.
79 Vector elements can be any C type e.g. (int, double, struct bar).
80 This is also true for data types built atop vectors (e.g. heap,
83 Many macros have \_a variants supporting alignment of vector elements
84 and \_h variants supporting non-zero-length vector headers. The \_ha
85 variants support both. Additionally cacheline alignment within a
86 vector element structure can be specified using the
87 CLIB_CACHE_LINE_ALIGN_MARK() macro.
89 Standard programming error: memorize a pointer to the ith element
90 of a vector then expand it. Vectors expand by 3/2, so such code
91 may appear to work for a period of time. Memorize vector indices
95 /** \brief Low-level (re)allocation function, usually not called directly
97 @param v pointer to a vector
98 @param n_elts requested number of elements
99 @param elt_sz requested size of one element
100 @param hdr_sz header size in bytes (may be zero)
101 @param align alignment (may be zero)
102 @return v_prime pointer to resized vector, may or may not equal v
104 void *_vec_realloc (void *v, uword n_elts, uword elt_sz, uword hdr_sz,
105 uword align, void *heap);
107 /* calculate minimum alignment out of data natural alignment and provided
108 * value, should not be < VEC_MIN_ALIGN */
109 static_always_inline uword
110 __vec_align (uword data_align, uword configuered_align)
112 data_align = clib_max (data_align, configuered_align);
113 ASSERT (count_set_bits (data_align) == 1);
114 return clib_max (VEC_MIN_ALIGN, data_align);
117 /* function used t o catch cases where vec_* macros on used on void * */
118 static_always_inline uword
119 __vec_elt_sz (uword elt_sz, int is_void)
121 /* vector macro operations on void * are not allowed */
122 ASSERT (is_void == 0);
126 static_always_inline void
127 _vec_update_pointer (void **vp, void *v)
129 /* avoid store if not needed */
134 static_always_inline void *
135 vec_get_heap (void *v)
137 if (v == 0 || _vec_find (v)->default_heap == 1)
139 return _vec_heap (v);
142 static_always_inline void *
143 _vec_realloc_inline (void *v, uword n_elts, uword elt_sz, uword hdr_sz,
144 uword align, void *heap)
146 if (PREDICT_TRUE (v != 0))
148 /* Vector header must start heap object. */
149 ASSERT (clib_mem_heap_is_heap_object (vec_get_heap (v), vec_header (v)));
151 /* Typically we'll not need to resize. */
152 if ((n_elts * elt_sz) <= vec_max_bytes (v))
154 _vec_set_len (v, n_elts, elt_sz);
159 /* Slow path: call helper function. */
160 return _vec_realloc (v, n_elts, elt_sz, hdr_sz, align, heap);
163 static_always_inline void
164 _vec_prealloc (void **vp, uword n_elts, uword hdr_sz, uword align, void *heap,
171 v = _vec_realloc (0, n_elts, elt_sz, hdr_sz, align, heap);
172 _vec_set_len (v, 0, elt_sz);
173 _vec_update_pointer (vp, v);
176 /** \brief Pre-allocate a vector (generic version)
178 @param V pointer to a vector
179 @param N number of elements to pre-allocate
180 @param H header size in bytes (may be zero)
181 @param A alignment (zero means default alignment of the data structure)
182 @param P heap (zero means default heap)
183 @return V (value-result macro parameter)
186 #define vec_prealloc_hap(V, N, H, A, P) \
187 _vec_prealloc ((void **) &(V), N, H, _vec_align (V, A), P, _vec_elt_sz (V))
189 /** \brief Pre-allocate a vector (simple version)
191 @param V pointer to a vector
192 @param N number of elements to pre-allocate
193 @return V (value-result macro parameter)
195 #define vec_prealloc(V, N) vec_prealloc_hap (V, N, 0, 0, 0)
197 /** \brief Pre-allocate a vector (heap version)
199 @param V pointer to a vector
200 @param N number of elements to pre-allocate
201 @param P heap (zero means default heap)
202 @return V (value-result macro parameter)
204 #define vec_prealloc_heap(V, N, P) vec_prealloc_hap (V, N, 0, 0, P)
207 _vec_resize_will_expand (void *v, uword n_elts, uword elt_sz)
212 /* Vector header must start heap object. */
213 ASSERT (clib_mem_heap_is_heap_object (vec_get_heap (v), vec_header (v)));
215 n_elts += _vec_len (v);
216 if ((n_elts * elt_sz) <= vec_max_bytes (v))
222 /** \brief Determine if vector will resize with next allocation
224 @param V pointer to a vector
225 @param N number of elements to add
226 @return 1 if vector will resize 0 otherwise
229 #define vec_resize_will_expand(V, N) \
230 _vec_resize_will_expand (V, N, _vec_elt_sz (V))
232 /* Local variable naming macro (prevents collisions with other macro naming). */
233 #define _v(var) _vec_##var
235 /** \brief Resize a vector (general version).
236 Add N elements to end of given vector V, return pointer to start of vector.
237 Vector will have room for H header bytes and will have user's data aligned
238 at alignment A (rounded to next power of 2).
240 @param V pointer to a vector
241 @param N number of elements to add
242 @param H header size in bytes (may be zero)
243 @param A alignment (may be zero)
244 @return V (value-result macro parameter)
247 static_always_inline void
248 _vec_resize (void **vp, uword n_add, uword hdr_sz, uword align, uword elt_sz)
251 v = _vec_realloc_inline (v, vec_len (v) + n_add, elt_sz, hdr_sz, align, 0);
252 _vec_update_pointer (vp, v);
255 #define vec_resize_ha(V, N, H, A) \
256 _vec_resize ((void **) &(V), N, H, _vec_align (V, A), _vec_elt_sz (V))
258 /** \brief Resize a vector (no header, unspecified alignment)
259 Add N elements to end of given vector V, return pointer to start of vector.
260 Vector will have room for H header bytes and will have user's data aligned
261 at alignment A (rounded to next power of 2).
263 @param V pointer to a vector
264 @param N number of elements to add
265 @return V (value-result macro parameter)
267 #define vec_resize(V,N) vec_resize_ha(V,N,0,0)
269 /** \brief Resize a vector (no header, alignment specified).
270 Add N elements to end of given vector V, return pointer to start of vector.
271 Vector will have room for H header bytes and will have user's data aligned
272 at alignment A (rounded to next power of 2).
274 @param V pointer to a vector
275 @param N number of elements to add
276 @param A alignment (may be zero)
277 @return V (value-result macro parameter)
280 #define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
282 /** \brief Allocate space for N more elements
284 @param V pointer to a vector
285 @param N number of elements to add
286 @param H header size in bytes (may be zero)
287 @param A alignment (may be zero)
288 @return V (value-result macro parameter)
291 #define vec_alloc_ha(V, N, H, A) \
294 uword _v (l) = vec_len (V); \
295 vec_resize_ha (V, N, H, A); \
296 vec_set_len (V, _v (l)); \
300 /** \brief Allocate space for N more elements
301 (no header, unspecified alignment)
303 @param V pointer to a vector
304 @param N number of elements to add
305 @return V (value-result macro parameter)
307 #define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
309 /** \brief Allocate space for N more elements (no header, given alignment)
310 @param V pointer to a vector
311 @param N number of elements to add
312 @param A alignment (may be zero)
313 @return V (value-result macro parameter)
316 #define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
318 /** \brief Create new vector of given type and length (general version).
319 @param T type of elements in new vector
320 @param N number of elements to add
321 @param H header size in bytes (may be zero)
322 @param A alignment (may be zero)
323 @param P heap (may be zero)
326 #define vec_new_generic(T, N, H, A, P) \
327 _vec_realloc (0, N, sizeof (T), H, _vec_align ((T *) 0, A), P)
329 /** \brief Create new vector of given type and length
330 (unspecified alignment, no header).
332 @param T type of elements in new vector
333 @param N number of elements to add
336 #define vec_new(T, N) vec_new_generic (T, N, 0, 0, 0)
337 /** \brief Create new vector of given type and length
338 (alignment specified, no header).
340 @param T type of elements in new vector
341 @param N number of elements to add
342 @param A alignment (may be zero)
345 #define vec_new_aligned(T, N, A) vec_new_generic (T, N, 0, A, 0)
346 /** \brief Create new vector of given type and length
347 (heap specified, no header).
349 @param T type of elements in new vector
350 @param N number of elements to add
351 @param P heap (may be zero)
354 #define vec_new_heap(T, N, P) vec_new_generic (T, N, 0, 0, P)
356 /** \brief Free vector's memory (no header).
357 @param V pointer to a vector
358 @return V (value-result parameter, V=0)
361 static_always_inline void
362 _vec_free (void **vp)
366 clib_mem_free (vec_header (vp[0]));
370 #define vec_free(V) _vec_free ((void **) &(V))
372 void vec_free_not_inline (void *v);
374 /**\brief Free vector user header (syntactic sugar)
375 @param h vector header
378 #define vec_free_header(h) clib_mem_free (h)
380 /** \brief Return copy of vector (general version).
382 @param V pointer to a vector
383 @param H size of header in bytes
384 @param A alignment (may be zero)
386 @return Vdup copy of vector
389 static_always_inline void *
390 _vec_dup (void *v, uword hdr_size, uword align, uword elt_sz)
392 uword len = vec_len (v);
397 n = _vec_realloc (0, len, elt_sz, hdr_size, align, 0);
398 clib_memcpy_fast (n, v, len * elt_sz);
403 #define vec_dup_ha(V, H, A) \
404 _vec_dup ((void *) (V), H, _vec_align (V, A), _vec_elt_sz (V))
406 /** \brief Return copy of vector (no header, no alignment)
408 @param V pointer to a vector
409 @return Vdup copy of vector
411 #define vec_dup(V) vec_dup_ha(V,0,0)
413 /** \brief Return copy of vector (no header, alignment specified).
415 @param V pointer to a vector
416 @param A alignment (may be zero)
418 @return Vdup copy of vector
420 #define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
422 /** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
425 @param DST destination
428 #define vec_copy(DST,SRC) clib_memcpy_fast (DST, SRC, vec_len (DST) * \
431 /** \brief Clone a vector. Make a new vector with the
432 same size as a given vector but possibly with a different type.
434 @param NEW_V pointer to new vector
435 @param OLD_V pointer to old vector
438 static_always_inline void
439 _vec_clone (void **v1p, void *v2, uword align, uword elt_sz)
441 v1p[0] = _vec_realloc (0, vec_len (v2), elt_sz, 0, align, 0);
443 #define vec_clone(NEW_V, OLD_V) \
444 _vec_clone ((void **) &(NEW_V), OLD_V, _vec_align (NEW_V, 0), \
447 /** \brief Make sure vector is long enough for given index (general version).
449 @param V (possibly NULL) pointer to a vector.
450 @param I vector index which will be valid upon return
451 @param H header size in bytes (may be zero)
452 @param A alignment (may be zero)
453 @return V (value-result macro parameter)
457 _vec_zero_elts (void *v, uword first, uword count, uword elt_sz)
459 clib_memset_u8 (v + (first * elt_sz), 0, count * elt_sz);
461 #define vec_zero_elts(V, F, C) _vec_zero_elts (V, F, C, sizeof ((V)[0]))
463 static_always_inline void
464 _vec_validate (void **vp, uword index, uword header_size, uword align,
465 void *heap, uword elt_sz)
468 uword vl = vec_len (v);
471 v = _vec_realloc_inline (v, index + 1, elt_sz, header_size, align, heap);
472 _vec_zero_elts (v, vl, index - vl + 1, elt_sz);
473 _vec_update_pointer (vp, v);
477 #define vec_validate_hap(V, I, H, A, P) \
478 _vec_validate ((void **) &(V), I, H, _vec_align (V, A), 0, sizeof ((V)[0]))
480 /** \brief Make sure vector is long enough for given index
481 (no header, unspecified alignment)
483 @param V (possibly NULL) pointer to a vector.
484 @param I vector index which will be valid upon return
485 @return V (value-result macro parameter)
487 #define vec_validate(V, I) vec_validate_hap (V, I, 0, 0, 0)
489 /** \brief Make sure vector is long enough for given index
490 (no header, specified alignment)
492 @param V (possibly NULL) pointer to a vector.
493 @param I vector index which will be valid upon return
494 @param A alignment (may be zero)
495 @return V (value-result macro parameter)
498 #define vec_validate_aligned(V, I, A) vec_validate_hap (V, I, 0, A, 0)
500 /** \brief Make sure vector is long enough for given index
501 (no header, specified heap)
503 @param V (possibly NULL) pointer to a vector.
504 @param I vector index which will be valid upon return
505 @param H heap (may be zero)
506 @return V (value-result macro parameter)
509 #define vec_validate_heap(V, I, P) vec_validate_hap (V, I, 0, 0, P)
511 /** \brief Make sure vector is long enough for given index
512 and initialize empty space (general version)
514 @param V (possibly NULL) pointer to a vector.
515 @param I vector index which will be valid upon return
516 @param INIT initial value (can be a complex expression!)
517 @param H header size in bytes (may be zero)
518 @param A alignment (may be zero)
519 @return V (value-result macro parameter)
521 #define vec_validate_init_empty_ha(V, I, INIT, H, A) \
525 word _v (l) = vec_len (V); \
526 if (_v (i) >= _v (l)) \
528 vec_resize_ha (V, 1 + (_v (i) - _v (l)), H, A); \
529 while (_v (l) <= _v (i)) \
531 (V)[_v (l)] = (INIT); \
538 /** \brief Make sure vector is long enough for given index
539 and initialize empty space (no header, unspecified alignment)
541 @param V (possibly NULL) pointer to a vector.
542 @param I vector index which will be valid upon return
543 @param INIT initial value (can be a complex expression!)
544 @return V (value-result macro parameter)
547 #define vec_validate_init_empty(V,I,INIT) \
548 vec_validate_init_empty_ha(V,I,INIT,0,0)
550 /** \brief Make sure vector is long enough for given index
551 and initialize empty space (no header, alignment alignment)
553 @param V (possibly NULL) pointer to a vector.
554 @param I vector index which will be valid upon return
555 @param INIT initial value (can be a complex expression!)
556 @param A alignment (may be zero)
557 @return V (value-result macro parameter)
559 #define vec_validate_init_empty_aligned(V,I,INIT,A) \
560 vec_validate_init_empty_ha(V,I,INIT,0,A)
562 /** \brief Add 1 element to end of vector (general version).
564 @param V pointer to a vector
565 @param E element to add
566 @param H header size in bytes (may be zero)
567 @param A alignment (may be zero)
568 @return V (value-result macro parameter)
571 static_always_inline void *
572 _vec_add1 (void **vp, uword hdr_sz, uword align, uword elt_sz)
575 uword len = vec_len (v);
576 v = _vec_realloc_inline (v, len + 1, elt_sz, hdr_sz, align, 0);
578 _vec_update_pointer (vp, v);
580 return v + len * elt_sz;
583 #define vec_add1_ha(V, E, H, A) \
584 ((__typeof__ ((V)[0]) *) _vec_add1 ((void **) &(V), H, _vec_align (V, A), \
585 _vec_elt_sz (V)))[0] = (E)
587 /** \brief Add 1 element to end of vector (unspecified alignment).
589 @param V pointer to a vector
590 @param E element to add
591 @return V (value-result macro parameter)
593 #define vec_add1(V,E) vec_add1_ha(V,E,0,0)
595 /** \brief Add 1 element to end of vector (alignment specified).
597 @param V pointer to a vector
598 @param E element to add
599 @param A alignment (may be zero)
600 @return V (value-result macro parameter)
602 #define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
604 /** \brief Add N elements to end of vector V,
605 return pointer to new elements in P. (general version)
607 @param V pointer to a vector
608 @param P pointer to new vector element(s)
609 @param N number of elements to add
610 @param H header size in bytes (may be zero)
611 @param A alignment (may be zero)
612 @return V and P (value-result macro parameters)
615 static_always_inline void
616 _vec_add2 (void **vp, void **pp, uword n_add, uword hdr_sz, uword align,
620 uword len = vec_len (vp[0]);
621 v = _vec_realloc_inline (v, len + n_add, elt_sz, hdr_sz, align, 0);
622 _vec_update_pointer (vp, v);
623 pp[0] = v + len * elt_sz;
626 #define vec_add2_ha(V, P, N, H, A) \
627 _vec_add2 ((void **) &(V), (void **) &(P), N, H, _vec_align (V, A), \
630 /** \brief Add N elements to end of vector V,
631 return pointer to new elements in P. (no header, unspecified alignment)
633 @param V pointer to a vector
634 @param P pointer to new vector element(s)
635 @param N number of elements to add
636 @return V and P (value-result macro parameters)
639 #define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
641 /** \brief Add N elements to end of vector V,
642 return pointer to new elements in P. (no header, alignment specified)
644 @param V pointer to a vector
645 @param P pointer to new vector element(s)
646 @param N number of elements to add
647 @param A alignment (may be zero)
648 @return V and P (value-result macro parameters)
651 #define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
653 /** \brief Add N elements to end of vector V (general version)
655 @param V pointer to a vector
656 @param E pointer to element(s) to add
657 @param N number of elements to add
658 @param H header size in bytes (may be zero)
659 @param A alignment (may be zero)
660 @return V (value-result macro parameter)
662 static_always_inline void
663 _vec_add (void **vp, void *e, word n_add, uword hdr_sz, uword align,
667 uword len = vec_len (v);
674 v = _vec_realloc_inline (v, len + n_add, elt_sz, hdr_sz, align, 0);
675 clib_memcpy_fast (v + len * elt_sz, e, n_add * elt_sz);
676 _vec_update_pointer (vp, v);
679 #define vec_add_ha(V, E, N, H, A) \
680 _vec_add ((void **) &(V), (void *) (E), N, H, _vec_align (V, A), \
683 /** \brief Add N elements to end of vector V (no header, unspecified alignment)
685 @param V pointer to a vector
686 @param E pointer to element(s) to add
687 @param N number of elements to add
688 @return V (value-result macro parameter)
690 #define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
692 /** \brief Add N elements to end of vector V (no header, specified alignment)
694 @param V pointer to a vector
695 @param E pointer to element(s) to add
696 @param N number of elements to add
697 @param A alignment (may be zero)
698 @return V (value-result macro parameter)
700 #define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
702 /** \brief Returns last element of a vector and decrements its length
704 @param V pointer to a vector
705 @return E element removed from the end of the vector
709 uword _v (l) = vec_len (V); \
710 __typeof__ ((V)[0]) _v (rv); \
711 ASSERT (_v (l) > 0); \
713 _v (rv) = (V)[_v (l)]; \
714 vec_set_len (V, _v (l)); \
718 /** \brief Set E to the last element of a vector, decrement vector length
719 @param V pointer to a vector
720 @param E pointer to the last vector element
721 @return E element removed from the end of the vector
722 (value-result macro parameter
725 #define vec_pop2(V,E) \
727 uword _v(l) = vec_len (V); \
728 if (_v(l) > 0) (E) = vec_pop (V); \
732 /** \brief Insert N vector elements starting at element M,
733 initialize new elements (general version).
735 @param V (possibly NULL) pointer to a vector.
736 @param N number of elements to insert
737 @param M insertion point
738 @param INIT initial value (can be a complex expression!)
739 @param H header size in bytes (may be zero)
740 @param A alignment (may be zero)
741 @return V (value-result macro parameter)
744 static_always_inline void
745 _vec_insert (void **vp, uword n_insert, uword ins_pt, u8 init, uword hdr_sz,
746 uword align, uword elt_sz)
749 uword len = vec_len (v);
751 ASSERT (ins_pt <= len);
753 v = _vec_realloc_inline (v, len + n_insert, elt_sz, hdr_sz, align, 0);
754 clib_memmove (v + elt_sz * (ins_pt + n_insert), v + ins_pt * elt_sz,
755 (len - ins_pt) * elt_sz);
756 _vec_zero_elts (v, ins_pt, n_insert, elt_sz);
757 _vec_update_pointer (vp, v);
760 #define vec_insert_init_empty_ha(V, N, M, INIT, H, A) \
761 _vec_insert ((void **) &(V), N, M, INIT, H, _vec_align (V, A), \
764 /** \brief Insert N vector elements starting at element M,
765 initialize new elements to zero (general version)
767 @param V (possibly NULL) pointer to a vector.
768 @param N number of elements to insert
769 @param M insertion point
770 @param H header size in bytes (may be zero)
771 @param A alignment (may be zero)
772 @return V (value-result macro parameter)
774 #define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
776 /** \brief Insert N vector elements starting at element M,
777 initialize new elements to zero (no header, unspecified alignment)
779 @param V (possibly NULL) pointer to a vector.
780 @param N number of elements to insert
781 @param M insertion point
782 @return V (value-result macro parameter)
784 #define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
786 /** \brief Insert N vector elements starting at element M,
787 initialize new elements to zero (no header, alignment specified)
789 @param V (possibly NULL) pointer to a vector.
790 @param N number of elements to insert
791 @param M insertion point
792 @param A alignment (may be zero)
793 @return V (value-result macro parameter)
795 #define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
797 /** \brief Insert N vector elements starting at element M,
798 initialize new elements (no header, unspecified alignment)
800 @param V (possibly NULL) pointer to a vector.
801 @param N number of elements to insert
802 @param M insertion point
803 @param INIT initial value (can be a complex expression!)
804 @return V (value-result macro parameter)
807 #define vec_insert_init_empty(V,N,M,INIT) \
808 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
809 /* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
811 /** \brief Insert N vector elements starting at element M,
812 initialize new elements (no header, specified alignment)
814 @param V (possibly NULL) pointer to a vector.
815 @param N number of elements to insert
816 @param M insertion point
817 @param INIT initial value (can be a complex expression!)
818 @param A alignment (may be zero)
819 @return V (value-result macro parameter)
821 #define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
822 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
824 /** \brief Insert N vector elements starting at element M,
825 insert given elements (general version)
827 @param V (possibly NULL) pointer to a vector.
828 @param E element(s) to insert
829 @param N number of elements to insert
830 @param M insertion point
831 @param H header size in bytes (may be zero)
832 @param A alignment (may be zero)
833 @return V (value-result macro parameter)
836 static_always_inline void
837 _vec_insert_elts (void **vp, void *e, uword n_insert, uword ins_pt,
838 uword hdr_sz, uword align, uword elt_sz)
841 uword len = vec_len (v);
843 ASSERT (ins_pt <= len);
845 v = _vec_realloc_inline (v, len + n_insert, elt_sz, hdr_sz, align, 0);
846 clib_memmove (v + elt_sz * (ins_pt + n_insert), v + ins_pt * elt_sz,
847 (len - ins_pt) * elt_sz);
848 _vec_zero_elts (v, ins_pt, n_insert, elt_sz);
849 clib_memcpy_fast (v + ins_pt * elt_sz, e, n_insert * elt_sz);
850 _vec_update_pointer (vp, v);
853 #define vec_insert_elts_ha(V, E, N, M, H, A) \
854 _vec_insert_elts ((void **) &(V), E, N, M, H, _vec_align (V, A), \
857 /** \brief Insert N vector elements starting at element M,
858 insert given elements (no header, unspecified alignment)
860 @param V (possibly NULL) pointer to a vector.
861 @param E element(s) to insert
862 @param N number of elements to insert
863 @param M insertion point
864 @return V (value-result macro parameter)
866 #define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
868 /** \brief Insert N vector elements starting at element M,
869 insert given elements (no header, specified alignment)
871 @param V (possibly NULL) pointer to a vector.
872 @param E element(s) to insert
873 @param N number of elements to insert
874 @param M insertion point
875 @param A alignment (may be zero)
876 @return V (value-result macro parameter)
878 #define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
880 /** \brief Delete N elements starting at element M
882 @param V pointer to a vector
883 @param N number of elements to delete
884 @param M first element to delete
885 @return V (value-result macro parameter)
888 static_always_inline void
889 _vec_delete (void *v, uword n_del, uword first, uword elt_sz)
891 word n_bytes_del, n_bytes_to_move, len = vec_len (v);
897 ASSERT (first + n_del <= len);
899 n_bytes_del = n_del * elt_sz;
900 n_bytes_to_move = (len - first - n_del) * elt_sz;
901 dst = v + first * elt_sz;
903 if (n_bytes_to_move > 0)
904 clib_memmove (dst, dst + n_bytes_del, n_bytes_to_move);
905 clib_memset (dst + n_bytes_to_move, 0, n_bytes_del);
907 _vec_set_len (v, _vec_len (v) - n_del, elt_sz);
910 #define vec_delete(V, N, M) _vec_delete ((void *) (V), N, M, _vec_elt_sz (V))
912 /** \brief Delete the element at index I
914 @param V pointer to a vector
915 @param I index to delete
918 static_always_inline void
919 _vec_del1 (void *v, uword index, uword elt_sz)
921 uword len = _vec_len (v) - 1;
924 clib_memcpy_fast (v + index * elt_sz, v + len * elt_sz, elt_sz);
926 _vec_set_len (v, len, elt_sz);
929 #define vec_del1(v, i) _vec_del1 ((void *) (v), i, _vec_elt_sz (v))
931 static_always_inline void
932 _vec_append (void **v1p, void *v2, uword v1_elt_sz, uword v2_elt_sz,
936 uword len1 = vec_len (v1);
937 uword len2 = vec_len (v2);
939 if (PREDICT_TRUE (len2 > 0))
941 v1 = _vec_realloc_inline (v1, len1 + len2, v2_elt_sz, 0, align, 0);
942 clib_memcpy_fast (v1 + len1 * v1_elt_sz, v2, len2 * v2_elt_sz);
943 _vec_update_pointer (v1p, v1);
947 /** \brief Append v2 after v1. Result in v1. Specified alignment.
948 @param V1 target vector
949 @param V2 vector to append
950 @param align required alignment
953 #define vec_append_aligned(v1, v2, align) \
954 _vec_append ((void **) &(v1), (void *) (v2), _vec_elt_sz (v1), \
955 _vec_elt_sz (v2), _vec_align (v1, align))
957 /** \brief Append v2 after v1. Result in v1.
958 @param V1 target vector
959 @param V2 vector to append
962 #define vec_append(v1, v2) vec_append_aligned (v1, v2, 0)
964 static_always_inline void
965 _vec_prepend (void **v1p, void *v2, uword v1_elt_sz, uword v2_elt_sz,
969 uword len1 = vec_len (v1);
970 uword len2 = vec_len (v2);
972 if (PREDICT_TRUE (len2 > 0))
974 v1 = _vec_realloc_inline (v1, len1 + len2, v2_elt_sz, 0, align, 0);
975 clib_memmove (v1 + len2 * v2_elt_sz, v1p[0], len1 * v1_elt_sz);
976 clib_memcpy_fast (v1, v2, len2 * v2_elt_sz);
977 _vec_update_pointer (v1p, v1);
981 /** \brief Prepend v2 before v1. Result in v1. Specified alignment
982 @param V1 target vector
983 @param V2 vector to prepend
984 @param align required alignment
987 #define vec_prepend_aligned(v1, v2, align) \
988 _vec_prepend ((void **) &(v1), (void *) (v2), _vec_elt_sz (v1), \
989 _vec_elt_sz (v2), _vec_align (v1, align))
991 /** \brief Prepend v2 before v1. Result in v1.
992 @param V1 target vector
993 @param V2 vector to prepend
996 #define vec_prepend(v1, v2) vec_prepend_aligned (v1, v2, 0)
998 /** \brief Zero all vector elements. Null-pointer tolerant.
999 @param var Vector to zero
1001 static_always_inline void
1002 _vec_zero (void *v, uword elt_sz)
1004 uword len = vec_len (v);
1007 clib_memset_u8 (v, 0, len * elt_sz);
1010 #define vec_zero(var) _vec_zero ((void *) (var), _vec_elt_sz (var))
1012 /** \brief Set all vector elements to given value. Null-pointer tolerant.
1013 @param v vector to set
1014 @param val value for each vector element
1016 #define vec_set(v,val) \
1019 __typeof__ ((v)[0]) _val = (val); \
1020 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
1021 (v)[_v(i)] = _val; \
1025 #include <stdlib.h> /* for qsort */
1028 /** \brief Compare two vectors, not NULL-pointer tolerant
1030 @param v1 Pointer to a vector
1031 @param v2 Pointer to a vector
1032 @return 1 if equal, 0 if unequal
1034 static_always_inline int
1035 _vec_is_equal (void *v1, void *v2, uword v1_elt_sz, uword v2_elt_sz)
1037 uword vec_len_v1 = vec_len (v1);
1039 if ((vec_len_v1 != vec_len (v2)) || (v1_elt_sz != v2_elt_sz))
1042 if ((vec_len_v1 == 0) || (memcmp (v1, v2, vec_len_v1 * v1_elt_sz) == 0))
1048 #define vec_is_equal(v1, v2) \
1049 _vec_is_equal ((void *) (v1), (void *) (v2), _vec_elt_sz (v1), \
1052 /** \brief Compare two vectors (only applicable to vectors of signed numbers).
1053 Used in qsort compare functions.
1055 @param v1 Pointer to a vector
1056 @param v2 Pointer to a vector
1059 #define vec_cmp(v1,v2) \
1061 word _v(i), _v(cmp), _v(l); \
1062 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
1064 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
1065 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
1069 if (_v(cmp) == 0 && _v(l) > 0) \
1070 _v(cmp) = vec_len(v1) - vec_len(v2); \
1071 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
1074 /** \brief Search a vector for the index of the entry that matches.
1076 @param v Pointer to a vector
1077 @param E Entry to match
1078 @return index of match or ~0
1080 #define vec_search(v,E) \
1083 while (_v(i) < vec_len(v)) \
1085 if ((v)[_v(i)] == E) \
1089 if (_v(i) == vec_len(v)) \
1094 /** \brief Search a vector for the index of the entry that matches.
1096 @param v Pointer to a vector
1097 @param E Pointer to entry to match
1098 @param fn Comparison function !0 => match
1099 @return index of match or ~0
1101 #define vec_search_with_function(v,E,fn) \
1104 while (_v(i) < vec_len(v)) \
1106 if (0 != fn(&(v)[_v(i)], (E))) \
1110 if (_v(i) == vec_len(v)) \
1115 /** \brief Sort a vector using the supplied element comparison function
1117 Does not depend on the underlying implementation to deal correctly
1118 with null, zero-long, or 1-long vectors
1120 @param vec vector to sort
1121 @param f comparison function
1123 #define vec_sort_with_function(vec,f) \
1125 if (vec_len (vec) > 1) \
1126 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
1129 /** \brief Make a vector containing a NULL terminated c-string.
1131 @param V (possibly NULL) pointer to a vector.
1132 @param S pointer to string buffer.
1133 @param L string length (NOT including the terminating NULL; a la strlen())
1135 #define vec_validate_init_c_string(V, S, L) \
1138 vec_reset_length (V); \
1139 vec_validate (V, (L)); \
1141 clib_memcpy_fast (V, (S), (L)); \
1146 /** \brief Test whether a vector is a NULL terminated c-string.
1148 @param V (possibly NULL) pointer to a vector.
1149 @return BOOLEAN indicating if the vector c-string is null terminated.
1151 #define vec_c_string_is_terminated(V) \
1152 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
1154 /** \brief (If necessary) NULL terminate a vector containing a c-string.
1156 @param V (possibly NULL) pointer to a vector.
1157 @return V (value-result macro parameter)
1159 #define vec_terminate_c_string(V) \
1162 if (!vec_c_string_is_terminated (V)) \
1167 #endif /* included_vec_h */