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 (aligned to uword boundary)
56 vector length: number of elements
57 user's pointer-> vector element #0
62 The user pointer contains the address of vector element # 0. Null
63 pointer vectors are valid and mean a zero length vector.
65 You can reset the length of an allocated vector to zero via the
66 vec_reset_length(v) macro, or by setting the vector length field to
67 zero (e.g. _vec_len (v) = 0). Vec_reset_length(v) preferred: it
68 understands Null pointers.
70 Typically, the header is not present. Headers allow for other
71 data structures to be built atop CLIB vectors.
73 Users may specify the alignment for first data element of a vector
74 via the vec_*_aligned macros.
76 Vector elements can be any C type e.g. (int, double, struct bar).
77 This is also true for data types built atop vectors (e.g. heap,
80 Many macros have \_a variants supporting alignment of vector elements
81 and \_h variants supporting non-zero-length vector headers. The \_ha
82 variants support both. Additionally cacheline alignment within a
83 vector element structure can be specified using the
84 CLIB_CACHE_LINE_ALIGN_MARK() macro.
86 Standard programming error: memorize a pointer to the ith element
87 of a vector then expand it. Vectors expand by 3/2, so such code
88 may appear to work for a period of time. Memorize vector indices
92 /** \brief Low-level resize allocation function, usually not called directly
94 @param v pointer to a vector
95 @param length_increment length increment in elements
96 @param data_bytes requested size in bytes
97 @param header_bytes header size in bytes (may be zero)
98 @param data_align alignment (may be zero)
99 @param numa_id numa id (may be zero)
100 @return v_prime pointer to resized vector, may or may not equal v
102 void *vec_resize_allocate_memory (void *v,
103 word length_increment,
105 uword header_bytes, uword data_align,
108 /** \brief Low-level vector resize function, usually not called directly
110 @param v pointer to a vector
111 @param length_increment length increment in elements
112 @param data_bytes requested size in bytes
113 @param header_bytes header size in bytes (may be zero)
114 @param data_align alignment (may be zero)
115 @param numa_id (may be ~0)
116 @return v_prime pointer to resized vector, may or may not equal v
119 #define _vec_resize_numa(V,L,DB,HB,A,S) \
121 __typeof__ ((V)) _V; \
122 _V = _vec_resize_inline((void *)V,L,DB,HB,clib_max((__alignof__((V)[0])),(A)),(S)); \
126 #define _vec_resize(V,L,DB,HB,A) \
127 _vec_resize_numa(V,L,DB,HB,A,VEC_NUMA_UNSPECIFIED)
130 _vec_resize_inline (void *v,
131 word length_increment,
132 uword data_bytes, uword header_bytes, uword data_align,
135 vec_header_t *vh = _vec_find (v);
136 uword new_data_bytes, aligned_header_bytes;
139 aligned_header_bytes = vec_header_bytes (header_bytes);
141 new_data_bytes = data_bytes + aligned_header_bytes;
143 if (PREDICT_TRUE (v != 0))
145 void *p = v - aligned_header_bytes;
147 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
149 oldheap = clib_mem_get_per_cpu_heap ();
150 clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap (numa_id));
153 /* Vector header must start heap object. */
154 ASSERT (clib_mem_is_heap_object (p));
156 /* Typically we'll not need to resize. */
157 if (new_data_bytes <= clib_mem_size (p))
159 CLIB_MEM_UNPOISON (v, data_bytes);
160 vh->len += length_increment;
161 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
162 clib_mem_set_per_cpu_heap (oldheap);
165 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
166 clib_mem_set_per_cpu_heap (oldheap);
169 /* Slow path: call helper function. */
170 return vec_resize_allocate_memory (v, length_increment, data_bytes,
172 clib_max (sizeof (vec_header_t),
173 data_align), numa_id);
176 /** \brief Determine if vector will resize with next allocation
178 @param v pointer to a vector
179 @param length_increment length increment in elements
180 @param data_bytes requested size in bytes
181 @param header_bytes header size in bytes (may be zero)
182 @param data_align alignment (may be zero)
183 @return 1 if vector will resize 0 otherwise
187 _vec_resize_will_expand (void *v,
188 word length_increment,
189 uword data_bytes, uword header_bytes,
192 uword new_data_bytes, aligned_header_bytes;
194 aligned_header_bytes = vec_header_bytes (header_bytes);
196 new_data_bytes = data_bytes + aligned_header_bytes;
198 if (PREDICT_TRUE (v != 0))
200 void *p = v - aligned_header_bytes;
202 /* Vector header must start heap object. */
203 ASSERT (clib_mem_is_heap_object (p));
205 /* Typically we'll not need to resize. */
206 if (new_data_bytes <= clib_mem_size (p))
212 /** \brief Predicate function, says whether the supplied vector is a clib heap
213 object (general version).
215 @param v pointer to a vector
216 @param header_bytes vector header size in bytes (may be zero)
219 uword clib_mem_is_vec_h (void *v, uword header_bytes);
222 /** \brief Predicate function, says whether the supplied vector is a clib heap
225 @param v pointer to a vector
229 clib_mem_is_vec (void *v)
231 return clib_mem_is_vec_h (v, 0);
234 /* Local variable naming macro (prevents collisions with other macro naming). */
235 #define _v(var) _vec_##var
237 /** \brief Resize a vector (general version).
238 Add N elements to end of given vector V, return pointer to start of vector.
239 Vector will have room for H header bytes and will have user's data aligned
240 at alignment A (rounded to next power of 2).
242 @param V pointer to a vector
243 @param N number of elements to add
244 @param H header size in bytes (may be zero)
245 @param A alignment (may be zero)
246 @param S numa_id (may be zero)
247 @return V (value-result macro parameter)
250 #define vec_resize_has(V,N,H,A,S) \
253 word _v(l) = vec_len (V); \
254 V = _vec_resize_numa ((V), _v(n), \
255 (_v(l) + _v(n)) * sizeof ((V)[0]), \
259 /** \brief Resize a vector (less general version).
260 Add N elements to end of given vector V, return pointer to start of vector.
261 Vector will have room for H header bytes and will have user's data aligned
262 at alignment A (rounded to next power of 2).
264 @param V pointer to a vector
265 @param N number of elements to add
266 @param H header size in bytes (may be zero)
267 @param A alignment (may be zero)
268 @return V (value-result macro parameter)
270 #define vec_resize_ha(V,N,H,A) vec_resize_has(V,N,H,A,VEC_NUMA_UNSPECIFIED)
272 /** \brief Resize a vector (no header, unspecified alignment)
273 Add N elements to end of given vector V, return pointer to start of vector.
274 Vector will have room for H header bytes and will have user's data aligned
275 at alignment A (rounded to next power of 2).
277 @param V pointer to a vector
278 @param N number of elements to add
279 @return V (value-result macro parameter)
281 #define vec_resize(V,N) vec_resize_ha(V,N,0,0)
283 /** \brief Resize a vector (no header, alignment specified).
284 Add N elements to end of given vector V, return pointer to start of vector.
285 Vector will have room for H header bytes and will have user's data aligned
286 at alignment A (rounded to next power of 2).
288 @param V pointer to a vector
289 @param N number of elements to add
290 @param A alignment (may be zero)
291 @return V (value-result macro parameter)
294 #define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
296 /** \brief Allocate space for N more elements
298 @param V pointer to a vector
299 @param N number of elements to add
300 @param H header size in bytes (may be zero)
301 @param A alignment (may be zero)
302 @return V (value-result macro parameter)
305 #define vec_alloc_ha(V,N,H,A) \
307 uword _v(l) = vec_len (V); \
308 vec_resize_ha (V, N, H, A); \
309 _vec_len (V) = _v(l); \
312 /** \brief Allocate space for N more elements
313 (no header, unspecified alignment)
315 @param V pointer to a vector
316 @param N number of elements to add
317 @return V (value-result macro parameter)
319 #define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
321 /** \brief Allocate space for N more elements (no header, given alignment)
322 @param V pointer to a vector
323 @param N number of elements to add
324 @param A alignment (may be zero)
325 @return V (value-result macro parameter)
328 #define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
330 /** \brief Create new vector of given type and length (general version).
331 @param T type of elements in new vector
332 @param N number of elements to add
333 @param H header size in bytes (may be zero)
334 @param A alignment (may be zero)
337 #define vec_new_ha(T,N,H,A) \
340 (T *)_vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
343 /** \brief Create new vector of given type and length
344 (unspecified alignment, no header).
346 @param T type of elements in new vector
347 @param N number of elements to add
350 #define vec_new(T,N) vec_new_ha(T,N,0,0)
351 /** \brief Create new vector of given type and length
352 (alignment specified, no header).
354 @param T type of elements in new vector
355 @param N number of elements to add
356 @param A alignment (may be zero)
359 #define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
361 /** \brief Free vector's memory (general version)
363 @param V pointer to a vector
364 @param H size of header in bytes
365 @return V (value-result parameter, V=0)
367 #define vec_free_h(V,H) \
371 clib_mem_free (vec_header ((V), (H))); \
376 /** \brief Free vector's memory (no header).
377 @param V pointer to a vector
378 @return V (value-result parameter, V=0)
380 #define vec_free(V) vec_free_h(V,0)
382 void vec_free_not_inline (void *v);
384 /**\brief Free vector user header (syntactic sugar)
385 @param h vector header
388 #define vec_free_header(h) clib_mem_free (h)
390 /** \brief Return copy of vector (general version).
392 @param V pointer to a vector
393 @param H size of header in bytes
394 @param A alignment (may be zero)
395 @param S numa (may be VEC_NUMA_UNSPECIFIED)
397 @return Vdup copy of vector
400 #define vec_dup_ha_numa(V,H,A,S) \
402 __typeof__ ((V)[0]) * _v(v) = 0; \
403 uword _v(l) = vec_len (V); \
406 vec_resize_has (_v(v), _v(l), (H), (A), (S)); \
407 clib_memcpy_fast (_v(v), (V), _v(l) * sizeof ((V)[0]));\
412 /** \brief Return copy of vector (VEC_NUMA_UNSPECIFIED).
414 @param V pointer to a vector
415 @param H size of header in bytes
416 @param A alignment (may be zero)
418 @return Vdup copy of vector
420 #define vec_dup_ha(V,H,A) \
421 vec_dup_ha_numa(V,H,A,VEC_NUMA_UNSPECIFIED)
424 /** \brief Return copy of vector (no header, no alignment)
426 @param V pointer to a vector
427 @return Vdup copy of vector
429 #define vec_dup(V) vec_dup_ha(V,0,0)
431 /** \brief Return copy of vector (no header, alignment specified).
433 @param V pointer to a vector
434 @param A alignment (may be zero)
436 @return Vdup copy of vector
438 #define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
440 /** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
443 @param DST destination
446 #define vec_copy(DST,SRC) clib_memcpy_fast (DST, SRC, vec_len (DST) * \
449 /** \brief Clone a vector. Make a new vector with the
450 same size as a given vector but possibly with a different type.
452 @param NEW_V pointer to new vector
453 @param OLD_V pointer to old vector
455 #define vec_clone(NEW_V,OLD_V) \
458 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
459 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
462 /** \brief Make sure vector is long enough for given index (general version).
464 @param V (possibly NULL) pointer to a vector.
465 @param I vector index which will be valid upon return
466 @param H header size in bytes (may be zero)
467 @param A alignment (may be zero)
468 @param N numa_id (may be zero)
469 @return V (value-result macro parameter)
472 #define vec_validate_han(V,I,H,A,N) \
475 STATIC_ASSERT(A==0 || ((A % sizeof(V[0]))==0) \
476 || ((sizeof(V[0]) % A) == 0), \
477 "vector validate aligned on incorrectly sized object"); \
479 word _v(l) = vec_len (V); \
480 if (_v(i) >= _v(l)) \
482 /* switch to the per-numa heap if directed */ \
483 if (PREDICT_FALSE(N != VEC_NUMA_UNSPECIFIED)) \
485 oldheap = clib_mem_get_per_cpu_heap(); \
486 clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap(N)); \
489 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
490 /* Must zero new space since user may have previously \
491 used e.g. _vec_len (v) -= 10 */ \
492 clib_memset ((V) + _v(l), 0, \
493 (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
494 /* Switch back to the global heap */ \
495 if (PREDICT_FALSE (N != VEC_NUMA_UNSPECIFIED)) \
496 clib_mem_set_per_cpu_heap (oldheap); \
500 #define vec_validate_ha(V,I,H,A) vec_validate_han(V,I,H,A,VEC_NUMA_UNSPECIFIED)
502 /** \brief Make sure vector is long enough for given index
503 (no header, unspecified alignment)
505 @param V (possibly NULL) pointer to a vector.
506 @param I vector index which will be valid upon return
507 @return V (value-result macro parameter)
509 #define vec_validate(V,I) vec_validate_ha(V,I,0,0)
511 /** \brief Make sure vector is long enough for given index
512 (no header, specified alignment)
514 @param V (possibly NULL) pointer to a vector.
515 @param I vector index which will be valid upon return
516 @param A alignment (may be zero)
517 @return V (value-result macro parameter)
520 #define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
522 /** \brief Make sure vector is long enough for given index
523 and initialize empty space (general version)
525 @param V (possibly NULL) pointer to a vector.
526 @param I vector index which will be valid upon return
527 @param INIT initial value (can be a complex expression!)
528 @param H header size in bytes (may be zero)
529 @param A alignment (may be zero)
530 @return V (value-result macro parameter)
532 #define vec_validate_init_empty_ha(V,I,INIT,H,A) \
535 word _v(l) = vec_len (V); \
536 if (_v(i) >= _v(l)) \
538 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
539 while (_v(l) <= _v(i)) \
541 (V)[_v(l)] = (INIT); \
547 /** \brief Make sure vector is long enough for given index
548 and initialize empty space (no header, unspecified alignment)
550 @param V (possibly NULL) pointer to a vector.
551 @param I vector index which will be valid upon return
552 @param INIT initial value (can be a complex expression!)
553 @return V (value-result macro parameter)
556 #define vec_validate_init_empty(V,I,INIT) \
557 vec_validate_init_empty_ha(V,I,INIT,0,0)
559 /** \brief Make sure vector is long enough for given index
560 and initialize empty space (no header, alignment alignment)
562 @param V (possibly NULL) pointer to a vector.
563 @param I vector index which will be valid upon return
564 @param INIT initial value (can be a complex expression!)
565 @param A alignment (may be zero)
566 @return V (value-result macro parameter)
568 #define vec_validate_init_empty_aligned(V,I,INIT,A) \
569 vec_validate_init_empty_ha(V,I,INIT,0,A)
571 /** \brief Add 1 element to end of vector (general version).
573 @param V pointer to a vector
574 @param E element to add
575 @param H header size in bytes (may be zero)
576 @param A alignment (may be zero)
577 @return V (value-result macro parameter)
579 #define vec_add1_ha(V,E,H,A) \
581 word _v(l) = vec_len (V); \
582 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
586 /** \brief Add 1 element to end of vector (unspecified alignment).
588 @param V pointer to a vector
589 @param E element to add
590 @return V (value-result macro parameter)
592 #define vec_add1(V,E) vec_add1_ha(V,E,0,0)
594 /** \brief Add 1 element to end of vector (alignment specified).
596 @param V pointer to a vector
597 @param E element to add
598 @param A alignment (may be zero)
599 @return V (value-result macro parameter)
601 #define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
603 /** \brief Add N elements to end of vector V,
604 return pointer to new elements in P. (general version)
606 @param V pointer to a vector
607 @param P pointer to new vector element(s)
608 @param N number of elements to add
609 @param H header size in bytes (may be zero)
610 @param A alignment (may be zero)
611 @return V and P (value-result macro parameters)
613 #define vec_add2_ha(V,P,N,H,A) \
616 word _v(l) = vec_len (V); \
617 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
621 /** \brief Add N elements to end of vector V,
622 return pointer to new elements in P. (no header, unspecified alignment)
624 @param V pointer to a vector
625 @param P pointer to new vector element(s)
626 @param N number of elements to add
627 @return V and P (value-result macro parameters)
630 #define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
632 /** \brief Add N elements to end of vector V,
633 return pointer to new elements in P. (no header, alignment specified)
635 @param V pointer to a vector
636 @param P pointer to new vector element(s)
637 @param N number of elements to add
638 @param A alignment (may be zero)
639 @return V and P (value-result macro parameters)
642 #define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
644 /** \brief Add N elements to end of vector V (general version)
646 @param V pointer to a vector
647 @param E pointer to element(s) to add
648 @param N number of elements to add
649 @param H header size in bytes (may be zero)
650 @param A alignment (may be zero)
651 @return V (value-result macro parameter)
653 #define vec_add_ha(V,E,N,H,A) \
656 word _v(l) = vec_len (V); \
657 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
658 clib_memcpy_fast ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
661 /** \brief Add N elements to end of vector V (no header, unspecified alignment)
663 @param V pointer to a vector
664 @param E pointer to element(s) to add
665 @param N number of elements to add
666 @return V (value-result macro parameter)
668 #define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
670 /** \brief Add N elements to end of vector V (no header, specified alignment)
672 @param V pointer to a vector
673 @param E pointer to element(s) to add
674 @param N number of elements to add
675 @param A alignment (may be zero)
676 @return V (value-result macro parameter)
678 #define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
680 /** \brief Returns last element of a vector and decrements its length
682 @param V pointer to a vector
683 @return E element removed from the end of the vector
687 uword _v(l) = vec_len (V); \
688 ASSERT (_v(l) > 0); \
690 _vec_len (V) = _v (l); \
694 /** \brief Set E to the last element of a vector, decrement vector length
695 @param V pointer to a vector
696 @param E pointer to the last vector element
697 @return E element removed from the end of the vector
698 (value-result macro parameter
701 #define vec_pop2(V,E) \
703 uword _v(l) = vec_len (V); \
704 if (_v(l) > 0) (E) = vec_pop (V); \
708 /** \brief Insert N vector elements starting at element M,
709 initialize new elements (general version).
711 @param V (possibly NULL) pointer to a vector.
712 @param N number of elements to insert
713 @param M insertion point
714 @param INIT initial value (can be a complex expression!)
715 @param H header size in bytes (may be zero)
716 @param A alignment (may be zero)
717 @return V (value-result macro parameter)
719 #define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
721 word _v(l) = vec_len (V); \
724 V = _vec_resize ((V), \
726 (_v(l) + _v(n))*sizeof((V)[0]), \
728 ASSERT (_v(m) <= _v(l)); \
729 memmove ((V) + _v(m) + _v(n), \
731 (_v(l) - _v(m)) * sizeof ((V)[0])); \
732 clib_memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
735 /** \brief Insert N vector elements starting at element M,
736 initialize new elements to zero (general version)
738 @param V (possibly NULL) pointer to a vector.
739 @param N number of elements to insert
740 @param M insertion point
741 @param H header size in bytes (may be zero)
742 @param A alignment (may be zero)
743 @return V (value-result macro parameter)
745 #define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
747 /** \brief Insert N vector elements starting at element M,
748 initialize new elements to zero (no header, unspecified alignment)
750 @param V (possibly NULL) pointer to a vector.
751 @param N number of elements to insert
752 @param M insertion point
753 @return V (value-result macro parameter)
755 #define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
757 /** \brief Insert N vector elements starting at element M,
758 initialize new elements to zero (no header, alignment specified)
760 @param V (possibly NULL) pointer to a vector.
761 @param N number of elements to insert
762 @param M insertion point
763 @param A alignment (may be zero)
764 @return V (value-result macro parameter)
766 #define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
768 /** \brief Insert N vector elements starting at element M,
769 initialize new elements (no header, unspecified alignment)
771 @param V (possibly NULL) pointer to a vector.
772 @param N number of elements to insert
773 @param M insertion point
774 @param INIT initial value (can be a complex expression!)
775 @return V (value-result macro parameter)
778 #define vec_insert_init_empty(V,N,M,INIT) \
779 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
780 /* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
782 /** \brief Insert N vector elements starting at element M,
783 initialize new elements (no header, specified alignment)
785 @param V (possibly NULL) pointer to a vector.
786 @param N number of elements to insert
787 @param M insertion point
788 @param INIT initial value (can be a complex expression!)
789 @param A alignment (may be zero)
790 @return V (value-result macro parameter)
792 #define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
793 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
795 /** \brief Insert N vector elements starting at element M,
796 insert given elements (general version)
798 @param V (possibly NULL) pointer to a vector.
799 @param E element(s) to insert
800 @param N number of elements to insert
801 @param M insertion point
802 @param H header size in bytes (may be zero)
803 @param A alignment (may be zero)
804 @return V (value-result macro parameter)
807 #define vec_insert_elts_ha(V,E,N,M,H,A) \
809 word _v(l) = vec_len (V); \
812 V = _vec_resize ((V), \
814 (_v(l) + _v(n))*sizeof((V)[0]), \
816 ASSERT (_v(m) <= _v(l)); \
817 memmove ((V) + _v(m) + _v(n), \
819 (_v(l) - _v(m)) * sizeof ((V)[0])); \
820 clib_memcpy_fast ((V) + _v(m), (E), \
821 _v(n) * sizeof ((V)[0])); \
824 /** \brief Insert N vector elements starting at element M,
825 insert given elements (no header, unspecified alignment)
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 @return V (value-result macro parameter)
833 #define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
835 /** \brief Insert N vector elements starting at element M,
836 insert given elements (no header, specified alignment)
838 @param V (possibly NULL) pointer to a vector.
839 @param E element(s) to insert
840 @param N number of elements to insert
841 @param M insertion point
842 @param A alignment (may be zero)
843 @return V (value-result macro parameter)
845 #define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
847 /** \brief Delete N elements starting at element M
849 @param V pointer to a vector
850 @param N number of elements to delete
851 @param M first element to delete
852 @return V (value-result macro parameter)
854 #define vec_delete(V,N,M) \
856 word _v(l) = vec_len (V); \
859 /* Copy over deleted elements. */ \
860 if (_v(l) - _v(n) - _v(m) > 0) \
861 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
862 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
863 /* Zero empty space at end (for future re-allocation). */ \
865 clib_memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
866 _vec_len (V) -= _v(n); \
867 CLIB_MEM_POISON(vec_end(V), _v(n) * sizeof ((V)[0])); \
870 /** \brief Delete the element at index I
872 @param V pointer to a vector
873 @param I index to delete
875 #define vec_del1(v,i) \
877 uword _vec_del_l = _vec_len (v) - 1; \
878 uword _vec_del_i = (i); \
879 if (_vec_del_i < _vec_del_l) \
880 (v)[_vec_del_i] = (v)[_vec_del_l]; \
881 _vec_len (v) = _vec_del_l; \
882 CLIB_MEM_POISON(vec_end(v), sizeof ((v)[0])); \
885 /** \brief Append v2 after v1. Result in v1.
886 @param V1 target vector
887 @param V2 vector to append
890 #define vec_append(v1,v2) \
892 uword _v(l1) = vec_len (v1); \
893 uword _v(l2) = vec_len (v2); \
895 v1 = _vec_resize ((v1), _v(l2), \
896 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
897 clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
900 /** \brief Append v2 after v1. Result in v1. Specified alignment.
901 @param V1 target vector
902 @param V2 vector to append
903 @param align required alignment
906 #define vec_append_aligned(v1,v2,align) \
908 uword _v(l1) = vec_len (v1); \
909 uword _v(l2) = vec_len (v2); \
911 v1 = _vec_resize ((v1), _v(l2), \
912 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
913 clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
916 /** \brief Prepend v2 before v1. Result in v1.
917 @param V1 target vector
918 @param V2 vector to prepend
921 #define vec_prepend(v1,v2) \
923 uword _v(l1) = vec_len (v1); \
924 uword _v(l2) = vec_len (v2); \
926 v1 = _vec_resize ((v1), _v(l2), \
927 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
928 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
929 clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
932 /** \brief Prepend v2 before v1. Result in v1. Specified alignment
933 @param V1 target vector
934 @param V2 vector to prepend
935 @param align required alignment
938 #define vec_prepend_aligned(v1,v2,align) \
940 uword _v(l1) = vec_len (v1); \
941 uword _v(l2) = vec_len (v2); \
943 v1 = _vec_resize ((v1), _v(l2), \
944 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
945 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
946 clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
950 /** \brief Zero all vector elements. Null-pointer tolerant.
951 @param var Vector to zero
953 #define vec_zero(var) \
956 clib_memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
959 /** \brief Set all vector elements to given value. Null-pointer tolerant.
960 @param v vector to set
961 @param val value for each vector element
963 #define vec_set(v,val) \
966 __typeof__ ((v)[0]) _val = (val); \
967 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
972 #include <stdlib.h> /* for qsort */
975 /** \brief Compare two vectors, not NULL-pointer tolerant
977 @param v1 Pointer to a vector
978 @param v2 Pointer to a vector
979 @return 1 if equal, 0 if unequal
981 #define vec_is_equal(v1,v2) \
982 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
984 /** \brief Compare two vectors (only applicable to vectors of signed numbers).
985 Used in qsort compare functions.
987 @param v1 Pointer to a vector
988 @param v2 Pointer to a vector
991 #define vec_cmp(v1,v2) \
993 word _v(i), _v(cmp), _v(l); \
994 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
996 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
997 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
1001 if (_v(cmp) == 0 && _v(l) > 0) \
1002 _v(cmp) = vec_len(v1) - vec_len(v2); \
1003 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
1006 /** \brief Search a vector for the index of the entry that matches.
1008 @param v Pointer to a vector
1009 @param E Entry to match
1010 @return index of match or ~0
1012 #define vec_search(v,E) \
1015 while (_v(i) < vec_len(v)) \
1017 if ((v)[_v(i)] == E) \
1021 if (_v(i) == vec_len(v)) \
1026 /** \brief Search a vector for the index of the entry that matches.
1028 @param v Pointer to a vector
1029 @param E Pointer to entry to match
1030 @param fn Comparison function !0 => match
1031 @return index of match or ~0
1033 #define vec_search_with_function(v,E,fn) \
1036 while (_v(i) < vec_len(v)) \
1038 if (0 != fn(&(v)[_v(i)], (E))) \
1042 if (_v(i) == vec_len(v)) \
1047 /** \brief Sort a vector using the supplied element comparison function
1049 Does not depend on the underlying implementation to deal correctly
1050 with null, zero-long, or 1-long vectors
1052 @param vec vector to sort
1053 @param f comparison function
1055 #define vec_sort_with_function(vec,f) \
1057 if (vec_len (vec) > 1) \
1058 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
1061 /** \brief Make a vector containing a NULL terminated c-string.
1063 @param V (possibly NULL) pointer to a vector.
1064 @param S pointer to string buffer.
1065 @param L string length (NOT including the terminating NULL; a la strlen())
1067 #define vec_validate_init_c_string(V, S, L) \
1069 vec_reset_length (V); \
1070 vec_validate ((V), (L)); \
1072 clib_memcpy_fast ((V), (S), (L)); \
1077 /** \brief Test whether a vector is a NULL terminated c-string.
1079 @param V (possibly NULL) pointer to a vector.
1080 @return BOOLEAN indicating if the vector c-string is null terminated.
1082 #define vec_c_string_is_terminated(V) \
1083 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
1085 /** \brief (If necessary) NULL terminate a vector containing a c-string.
1087 @param V (possibly NULL) pointer to a vector.
1088 @return V (value-result macro parameter)
1090 #define vec_terminate_c_string(V) \
1092 u32 vl = vec_len ((V)); \
1093 if (!vec_c_string_is_terminated(V)) \
1095 vec_validate ((V), vl); \
1100 #endif /* included_vec_h */
1104 * fd.io coding-style-patch-verification: ON
1107 * eval: (c-set-style "gnu")