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 data elements via the
76 Vectors 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 data
81 and _h variants supporting non zero length vector headers.
82 The _ha variants support both.
84 Standard programming error: memorize a pointer to the ith element
85 of a vector then expand it. Vectors expand by 3/2, so such code
86 may appear to work for a period of time. Memorize vector indices
90 /** \brief Low-level resize allocation function, usually not called directly
92 @param v pointer to a vector
93 @param length_increment length increment in elements
94 @param data_bytes requested size in bytes
95 @param header_bytes header size in bytes (may be zero)
96 @param data_align alignment (may be zero)
97 @return v_prime pointer to resized vector, may or may not equal v
99 void *vec_resize_allocate_memory (void *v,
100 word length_increment,
102 uword header_bytes, uword data_align);
104 /** \brief Low-level vector resize function, usually not called directly
106 @param v pointer to a vector
107 @param length_increment length increment in elements
108 @param data_bytes requested size in bytes
109 @param header_bytes header size in bytes (may be zero)
110 @param data_align alignment (may be zero)
111 @return v_prime pointer to resized vector, may or may not equal v
115 _vec_resize (void *v,
116 word length_increment,
117 uword data_bytes, uword header_bytes, uword data_align)
119 vec_header_t *vh = _vec_find (v);
120 uword new_data_bytes, aligned_header_bytes;
122 aligned_header_bytes = vec_header_bytes (header_bytes);
124 new_data_bytes = data_bytes + aligned_header_bytes;
126 if (PREDICT_TRUE (v != 0))
128 void *p = v - aligned_header_bytes;
130 /* Vector header must start heap object. */
131 ASSERT (clib_mem_is_heap_object (p));
133 /* Typically we'll not need to resize. */
134 if (new_data_bytes <= clib_mem_size (p))
136 vh->len += length_increment;
141 /* Slow path: call helper function. */
142 return vec_resize_allocate_memory (v, length_increment, data_bytes,
144 clib_max (sizeof (vec_header_t),
148 /** \brief Determine if vector will resize with next allocation
150 @param v pointer to a vector
151 @param length_increment length increment in elements
152 @param data_bytes requested size in bytes
153 @param header_bytes header size in bytes (may be zero)
154 @param data_align alignment (may be zero)
155 @return 1 if vector will resize 0 otherwise
159 _vec_resize_will_expand (void *v,
160 word length_increment,
161 uword data_bytes, uword header_bytes,
164 uword new_data_bytes, aligned_header_bytes;
166 aligned_header_bytes = vec_header_bytes (header_bytes);
168 new_data_bytes = data_bytes + aligned_header_bytes;
170 if (PREDICT_TRUE (v != 0))
172 void *p = v - aligned_header_bytes;
174 /* Vector header must start heap object. */
175 ASSERT (clib_mem_is_heap_object (p));
177 /* Typically we'll not need to resize. */
178 if (new_data_bytes <= clib_mem_size (p))
184 /** \brief Predicate function, says whether the supplied vector is a clib heap
185 object (general version).
187 @param v pointer to a vector
188 @param header_bytes vector header size in bytes (may be zero)
191 uword clib_mem_is_vec_h (void *v, uword header_bytes);
194 /** \brief Predicate function, says whether the supplied vector is a clib heap
197 @param v pointer to a vector
201 clib_mem_is_vec (void *v)
203 return clib_mem_is_vec_h (v, 0);
206 /* Local variable naming macro (prevents collisions with other macro naming). */
207 #define _v(var) _vec_##var
209 /** \brief Resize a vector (general version).
210 Add N elements to end of given vector V, return pointer to start of vector.
211 Vector will have room for H header bytes and will have user's data aligned
212 at alignment A (rounded to next power of 2).
214 @param V pointer to a vector
215 @param N number of elements to add
216 @param H header size in bytes (may be zero)
217 @param A alignment (may be zero)
218 @return V (value-result macro parameter)
221 #define vec_resize_ha(V,N,H,A) \
224 word _v(l) = vec_len (V); \
225 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
228 /** \brief Resize a vector (no header, unspecified alignment)
229 Add N elements to end of given vector V, return pointer to start of vector.
230 Vector will have room for H header bytes and will have user's data aligned
231 at alignment A (rounded to next power of 2).
233 @param V pointer to a vector
234 @param N number of elements to add
235 @return V (value-result macro parameter)
237 #define vec_resize(V,N) vec_resize_ha(V,N,0,0)
239 /** \brief Resize a vector (no header, alignment specified).
240 Add N elements to end of given vector V, return pointer to start of vector.
241 Vector will have room for H header bytes and will have user's data aligned
242 at alignment A (rounded to next power of 2).
244 @param V pointer to a vector
245 @param N number of elements to add
246 @param A alignment (may be zero)
247 @return V (value-result macro parameter)
250 #define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
252 /** \brief Allocate space for N more elements
254 @param V pointer to a vector
255 @param N number of elements to add
256 @param H header size in bytes (may be zero)
257 @param A alignment (may be zero)
258 @return V (value-result macro parameter)
261 #define vec_alloc_ha(V,N,H,A) \
263 uword _v(l) = vec_len (V); \
264 vec_resize_ha (V, N, H, A); \
265 _vec_len (V) = _v(l); \
268 /** \brief Allocate space for N more elements
269 (no header, unspecified alignment)
271 @param V pointer to a vector
272 @param N number of elements to add
273 @return V (value-result macro parameter)
275 #define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
277 /** \brief Allocate space for N more elements (no header, given alignment)
278 @param V pointer to a vector
279 @param N number of elements to add
280 @param A alignment (may be zero)
281 @return V (value-result macro parameter)
284 #define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
286 /** \brief Create new vector of given type and length (general version).
287 @param T type of elements in new vector
288 @param N number of elements to add
289 @param H header size in bytes (may be zero)
290 @param A alignment (may be zero)
293 #define vec_new_ha(T,N,H,A) \
296 _vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
299 /** \brief Create new vector of given type and length
300 (unspecified alignment, no header).
302 @param T type of elements in new vector
303 @param N number of elements to add
306 #define vec_new(T,N) vec_new_ha(T,N,0,0)
307 /** \brief Create new vector of given type and length
308 (alignment specified, no header).
310 @param T type of elements in new vector
311 @param N number of elements to add
312 @param A alignment (may be zero)
315 #define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
317 /** \brief Free vector's memory (general version)
319 @param V pointer to a vector
320 @param H size of header in bytes
321 @return V (value-result parameter, V=0)
323 #define vec_free_h(V,H) \
327 clib_mem_free (vec_header ((V), (H))); \
332 /** \brief Free vector's memory (no header).
333 @param V pointer to a vector
334 @return V (value-result parameter, V=0)
336 #define vec_free(V) vec_free_h(V,0)
338 /**\brief Free vector user header (syntactic sugar)
339 @param h vector header
342 #define vec_free_header(h) clib_mem_free (h)
344 /** \brief Return copy of vector (general version).
346 @param V pointer to a vector
347 @param H size of header in bytes
348 @param A alignment (may be zero)
350 @return Vdup copy of vector
353 #define vec_dup_ha(V,H,A) \
355 __typeof__ ((V)[0]) * _v(v) = 0; \
356 uword _v(l) = vec_len (V); \
359 vec_resize_ha (_v(v), _v(l), (H), (A)); \
360 clib_memcpy (_v(v), (V), _v(l) * sizeof ((V)[0]));\
365 /** \brief Return copy of vector (no header, no alignment)
367 @param V pointer to a vector
368 @return Vdup copy of vector
370 #define vec_dup(V) vec_dup_ha(V,0,0)
372 /** \brief Return copy of vector (no header, alignment specified).
374 @param V pointer to a vector
375 @param A alignment (may be zero)
377 @return Vdup copy of vector
379 #define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
381 /** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
384 @param DST destination
387 #define vec_copy(DST,SRC) clib_memcpy (DST, SRC, vec_len (DST) * \
390 /** \brief Clone a vector. Make a new vector with the
391 same size as a given vector but possibly with a different type.
393 @param NEW_V pointer to new vector
394 @param OLD_V pointer to old vector
396 #define vec_clone(NEW_V,OLD_V) \
399 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
400 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
403 /** \brief Make sure vector is long enough for given index (general version).
405 @param V (possibly NULL) pointer to a vector.
406 @param I vector index which will be valid upon return
407 @param H header size in bytes (may be zero)
408 @param A alignment (may be zero)
409 @return V (value-result macro parameter)
412 #define vec_validate_ha(V,I,H,A) \
414 STATIC_ASSERT(A==0 || ((A % sizeof(V[0]))==0) || ((sizeof(V[0]) % A) == 0),\
415 "vector validate aligned on incorrectly sized object"); \
417 word _v(l) = vec_len (V); \
418 if (_v(i) >= _v(l)) \
420 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
421 /* Must zero new space since user may have previously \
422 used e.g. _vec_len (v) -= 10 */ \
423 memset ((V) + _v(l), 0, (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
427 /** \brief Make sure vector is long enough for given index
428 (no header, unspecified alignment)
430 @param V (possibly NULL) pointer to a vector.
431 @param I vector index which will be valid upon return
432 @return V (value-result macro parameter)
434 #define vec_validate(V,I) vec_validate_ha(V,I,0,0)
436 /** \brief Make sure vector is long enough for given index
437 (no header, specified alignment)
439 @param V (possibly NULL) pointer to a vector.
440 @param I vector index which will be valid upon return
441 @param A alignment (may be zero)
442 @return V (value-result macro parameter)
445 #define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
447 /** \brief Make sure vector is long enough for given index
448 and initialize empty space (general version)
450 @param V (possibly NULL) pointer to a vector.
451 @param I vector index which will be valid upon return
452 @param INIT initial value (can be a complex expression!)
453 @param H header size in bytes (may be zero)
454 @param A alignment (may be zero)
455 @return V (value-result macro parameter)
457 #define vec_validate_init_empty_ha(V,I,INIT,H,A) \
460 word _v(l) = vec_len (V); \
461 if (_v(i) >= _v(l)) \
463 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
464 while (_v(l) <= _v(i)) \
466 (V)[_v(l)] = (INIT); \
472 /** \brief Make sure vector is long enough for given index
473 and initialize empty space (no header, unspecified alignment)
475 @param V (possibly NULL) pointer to a vector.
476 @param I vector index which will be valid upon return
477 @param INIT initial value (can be a complex expression!)
478 @param H header size in bytes (may be zero)
479 @param A alignment (may be zero)
480 @return V (value-result macro parameter)
483 #define vec_validate_init_empty(V,I,INIT) \
484 vec_validate_init_empty_ha(V,I,INIT,0,0)
486 /** \brief Make sure vector is long enough for given index
487 and initialize empty space (no header, alignment alignment)
489 @param V (possibly NULL) pointer to a vector.
490 @param I vector index which will be valid upon return
491 @param INIT initial value (can be a complex expression!)
492 @param H header size in bytes (may be zero)
493 @param A alignment (may be zero)
494 @return V (value-result macro parameter)
496 #define vec_validate_init_empty_aligned(V,I,INIT,A) \
497 vec_validate_init_empty_ha(V,I,INIT,0,A)
499 /** \brief Add 1 element to end of vector (general version).
501 @param V pointer to a vector
502 @param E element to add
503 @param H header size in bytes (may be zero)
504 @param A alignment (may be zero)
505 @return V (value-result macro parameter)
507 #define vec_add1_ha(V,E,H,A) \
509 word _v(l) = vec_len (V); \
510 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
514 /** \brief Add 1 element to end of vector (unspecified alignment).
516 @param V pointer to a vector
517 @param E element to add
518 @return V (value-result macro parameter)
520 #define vec_add1(V,E) vec_add1_ha(V,E,0,0)
522 /** \brief Add 1 element to end of vector (alignment specified).
524 @param V pointer to a vector
525 @param E element to add
526 @param H header size in bytes (may be zero)
527 @param A alignment (may be zero)
528 @return V (value-result macro parameter)
530 #define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
532 /** \brief Add N elements to end of vector V,
533 return pointer to new elements in P. (general version)
535 @param V pointer to a vector
536 @param P pointer to new vector element(s)
537 @param N number of elements to add
538 @param H header size in bytes (may be zero)
539 @param A alignment (may be zero)
540 @return V and P (value-result macro parameters)
542 #define vec_add2_ha(V,P,N,H,A) \
545 word _v(l) = vec_len (V); \
546 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
550 /** \brief Add N elements to end of vector V,
551 return pointer to new elements in P. (no header, unspecified alignment)
553 @param V pointer to a vector
554 @param P pointer to new vector element(s)
555 @param N number of elements to add
556 @return V and P (value-result macro parameters)
559 #define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
561 /** \brief Add N elements to end of vector V,
562 return pointer to new elements in P. (no header, alignment specified)
564 @param V pointer to a vector
565 @param P pointer to new vector element(s)
566 @param N number of elements to add
567 @param A alignment (may be zero)
568 @return V and P (value-result macro parameters)
571 #define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
573 /** \brief Add N elements to end of vector V (general version)
575 @param V pointer to a vector
576 @param E pointer to element(s) to add
577 @param N number of elements to add
578 @param H header size in bytes (may be zero)
579 @param A alignment (may be zero)
580 @return V (value-result macro parameter)
582 #define vec_add_ha(V,E,N,H,A) \
585 word _v(l) = vec_len (V); \
586 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
587 clib_memcpy ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
590 /** \brief Add N elements to end of vector V (no header, unspecified alignment)
592 @param V pointer to a vector
593 @param E pointer to element(s) to add
594 @param N number of elements to add
595 @return V (value-result macro parameter)
597 #define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
599 /** \brief Add N elements to end of vector V (no header, specified alignment)
601 @param V pointer to a vector
602 @param E pointer to element(s) to add
603 @param N number of elements to add
604 @param A alignment (may be zero)
605 @return V (value-result macro parameter)
607 #define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
609 /** \brief Returns last element of a vector and decrements its length
611 @param V pointer to a vector
612 @return E element removed from the end of the vector
616 uword _v(l) = vec_len (V); \
617 ASSERT (_v(l) > 0); \
619 _vec_len (V) = _v (l); \
623 /** \brief Set E to the last element of a vector, decrement vector length
624 @param V pointer to a vector
625 @param E pointer to the last vector element
626 @return E element removed from the end of the vector
627 (value-result macro parameter
630 #define vec_pop2(V,E) \
632 uword _v(l) = vec_len (V); \
633 if (_v(l) > 0) (E) = vec_pop (V); \
637 /** \brief Insert N vector elements starting at element M,
638 initialize new elements (general version).
640 @param V (possibly NULL) pointer to a vector.
641 @param N number of elements to insert
642 @param M insertion point
643 @param INIT initial value (can be a complex expression!)
644 @param H header size in bytes (may be zero)
645 @param A alignment (may be zero)
646 @return V (value-result macro parameter)
648 #define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
650 word _v(l) = vec_len (V); \
653 V = _vec_resize ((V), \
655 (_v(l) + _v(n))*sizeof((V)[0]), \
657 ASSERT (_v(m) <= _v(l)); \
658 memmove ((V) + _v(m) + _v(n), \
660 (_v(l) - _v(m)) * sizeof ((V)[0])); \
661 memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
664 /** \brief Insert N vector elements starting at element M,
665 initialize new elements to zero (general version)
667 @param V (possibly NULL) pointer to a vector.
668 @param N number of elements to insert
669 @param M insertion point
670 @param H header size in bytes (may be zero)
671 @param A alignment (may be zero)
672 @return V (value-result macro parameter)
674 #define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
676 /** \brief Insert N vector elements starting at element M,
677 initialize new elements to zero (no header, unspecified alignment)
679 @param V (possibly NULL) pointer to a vector.
680 @param N number of elements to insert
681 @param M insertion point
682 @return V (value-result macro parameter)
684 #define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
686 /** \brief Insert N vector elements starting at element M,
687 initialize new elements to zero (no header, alignment specified)
689 @param V (possibly NULL) pointer to a vector.
690 @param N number of elements to insert
691 @param M insertion point
692 @param A alignment (may be zero)
693 @return V (value-result macro parameter)
695 #define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
697 /** \brief Insert N vector elements starting at element M,
698 initialize new elements (no header, unspecified alignment)
700 @param V (possibly NULL) pointer to a vector.
701 @param N number of elements to insert
702 @param M insertion point
703 @param INIT initial value (can be a complex expression!)
704 @return V (value-result macro parameter)
707 #define vec_insert_init_empty(V,N,M,INIT) \
708 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
709 /* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
711 /** \brief Insert N vector elements starting at element M,
712 initialize new elements (no header, specified alignment)
714 @param V (possibly NULL) pointer to a vector.
715 @param N number of elements to insert
716 @param M insertion point
717 @param INIT initial value (can be a complex expression!)
718 @param A alignment (may be zero)
719 @return V (value-result macro parameter)
721 #define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
722 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
724 /** \brief Insert N vector elements starting at element M,
725 insert given elements (general version)
727 @param V (possibly NULL) pointer to a vector.
728 @param E element(s) to insert
729 @param N number of elements to insert
730 @param M insertion point
731 @param H header size in bytes (may be zero)
732 @param A alignment (may be zero)
733 @return V (value-result macro parameter)
736 #define vec_insert_elts_ha(V,E,N,M,H,A) \
738 word _v(l) = vec_len (V); \
741 V = _vec_resize ((V), \
743 (_v(l) + _v(n))*sizeof((V)[0]), \
745 ASSERT (_v(m) <= _v(l)); \
746 memmove ((V) + _v(m) + _v(n), \
748 (_v(l) - _v(m)) * sizeof ((V)[0])); \
749 clib_memcpy ((V) + _v(m), (E), \
750 _v(n) * sizeof ((V)[0])); \
753 /** \brief Insert N vector elements starting at element M,
754 insert given elements (no header, unspecified alignment)
756 @param V (possibly NULL) pointer to a vector.
757 @param E element(s) to insert
758 @param N number of elements to insert
759 @param M insertion point
760 @return V (value-result macro parameter)
762 #define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
764 /** \brief Insert N vector elements starting at element M,
765 insert given elements (no header, specified alignment)
767 @param V (possibly NULL) pointer to a vector.
768 @param E element(s) to insert
769 @param N number of elements to insert
770 @param M insertion point
771 @param A alignment (may be zero)
772 @return V (value-result macro parameter)
774 #define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
776 /** \brief Delete N elements starting at element M
778 @param V pointer to a vector
779 @param N number of elements to delete
780 @param M first element to delete
781 @return V (value-result macro parameter)
783 #define vec_delete(V,N,M) \
785 word _v(l) = vec_len (V); \
788 /* Copy over deleted elements. */ \
789 if (_v(l) - _v(n) - _v(m) > 0) \
790 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
791 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
792 /* Zero empty space at end (for future re-allocation). */ \
794 memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
795 _vec_len (V) -= _v(n); \
798 /** \brief Delete the element at index I
800 @param V pointer to a vector
801 @param I index to delete
803 #define vec_del1(v,i) \
805 uword _vec_del_l = _vec_len (v) - 1; \
806 uword _vec_del_i = (i); \
807 if (_vec_del_i < _vec_del_l) \
808 (v)[_vec_del_i] = (v)[_vec_del_l]; \
809 _vec_len (v) = _vec_del_l; \
812 /** \brief Append v2 after v1. Result in v1.
813 @param V1 target vector
814 @param V2 vector to append
817 #define vec_append(v1,v2) \
819 uword _v(l1) = vec_len (v1); \
820 uword _v(l2) = vec_len (v2); \
822 v1 = _vec_resize ((v1), _v(l2), \
823 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
824 clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
827 /** \brief Append v2 after v1. Result in v1. Specified alignment.
828 @param V1 target vector
829 @param V2 vector to append
830 @param align required alignment
833 #define vec_append_aligned(v1,v2,align) \
835 uword _v(l1) = vec_len (v1); \
836 uword _v(l2) = vec_len (v2); \
838 v1 = _vec_resize ((v1), _v(l2), \
839 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
840 clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
843 /** \brief Prepend v2 before v1. Result in v1.
844 @param V1 target vector
845 @param V2 vector to prepend
848 #define vec_prepend(v1,v2) \
850 uword _v(l1) = vec_len (v1); \
851 uword _v(l2) = vec_len (v2); \
853 v1 = _vec_resize ((v1), _v(l2), \
854 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
855 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
856 clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
859 /** \brief Prepend v2 before v1. Result in v1. Specified alignment
860 @param V1 target vector
861 @param V2 vector to prepend
862 @param align required alignment
865 #define vec_prepend_aligned(v1,v2,align) \
867 uword _v(l1) = vec_len (v1); \
868 uword _v(l2) = vec_len (v2); \
870 v1 = _vec_resize ((v1), _v(l2), \
871 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
872 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
873 clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
877 /** \brief Zero all vector elements. Null-pointer tolerant.
878 @param var Vector to zero
880 #define vec_zero(var) \
883 memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
886 /** \brief Set all vector elements to given value. Null-pointer tolerant.
887 @param v vector to set
888 @param val value for each vector element
890 #define vec_set(v,val) \
893 __typeof__ ((v)[0]) _val = (val); \
894 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
899 #include <stdlib.h> /* for qsort */
902 /** \brief Compare two vectors, not NULL-pointer tolerant
904 @param v1 Pointer to a vector
905 @param v2 Pointer to a vector
906 @return 1 if equal, 0 if unequal
908 #define vec_is_equal(v1,v2) \
909 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
911 /** \brief Compare two vectors (only applicable to vectors of signed numbers).
912 Used in qsort compare functions.
914 @param v1 Pointer to a vector
915 @param v2 Pointer to a vector
918 #define vec_cmp(v1,v2) \
920 word _v(i), _v(cmp), _v(l); \
921 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
923 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
924 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
928 if (_v(cmp) == 0 && _v(l) > 0) \
929 _v(cmp) = vec_len(v1) - vec_len(v2); \
930 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
933 /** \brief Search a vector for the index of the entry that matches.
935 @param v1 Pointer to a vector
936 @param v2 Entry to match
937 @return index of match or ~0
939 #define vec_search(v,E) \
942 while (_v(i) < vec_len(v)) \
944 if ((v)[_v(i)] == E) \
948 if (_v(i) == vec_len(v)) \
953 /** \brief Sort a vector using the supplied element comparison function
955 @param vec vector to sort
956 @param f comparison function
958 #define vec_sort_with_function(vec,f) \
960 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
963 /** \brief Make a vector containing a NULL terminated c-string.
965 @param V (possibly NULL) pointer to a vector.
966 @param S pointer to string buffer.
967 @param L string length (NOT including the terminating NULL; a la strlen())
969 #define vec_validate_init_c_string(V, S, L) \
971 vec_reset_length (V); \
972 vec_validate ((V), (L)); \
974 clib_memcpy ((V), (S), (L)); \
979 /** \brief Test whether a vector is a NULL terminated c-string.
981 @param V (possibly NULL) pointer to a vector.
982 @return BOOLEAN indicating if the vector c-string is null terminated.
984 #define vec_c_string_is_terminated(V) \
985 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
987 /** \brief (If necessary) NULL terminate a vector containing a c-string.
989 @param V (possibly NULL) pointer to a vector.
990 @return V (value-result macro parameter)
992 #define vec_terminate_c_string(V) \
994 u32 vl = vec_len ((V)); \
995 if (!vec_c_string_is_terminated(V)) \
997 vec_validate ((V), vl); \
1002 #endif /* included_vec_h */
1006 * fd.io coding-style-patch-verification: ON
1009 * eval: (c-set-style "gnu")