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 A user is returned a pointer to element # 1.
63 Null pointer vectors are valid and mean a zero length vector.
64 You can also have an allocated non-null zero length vector by just
65 setting the vector length field to zero (e.g. _vec_len (v) = 0).
67 Typically, the header is not present. Headers allow for other
68 data structures to be built atop CLIB vectors.
70 Users may specify the alignment for data elements via the
73 Vectors elements can be any C type e.g. (int, double, struct bar).
74 This is also true for data types built atop vectors (e.g. heap,
77 Many macros have _a variants supporting alignment of vector data
78 and _h variants supporting non zero length vector headers.
79 The _ha variants support both.
81 Standard programming error: memorize a pointer to the ith element
82 of a vector then expand it. Vectors expand by 3/2, so such code
83 may appear to work for a period of time. Memorize vector indices
87 /** \brief Low-level resize allocation function, usually not called directly
89 @param v pointer to a vector
90 @param length_increment length increment in elements
91 @param data_bytes requested size in bytes
92 @param header_bytes header size in bytes (may be zero)
93 @param data_align alignment (may be zero)
94 @return v_prime pointer to resized vector, may or may not equal v
96 void * vec_resize_allocate_memory (void * v,
97 word length_increment,
102 /** \brief Low-level vector resize function, usually not called directly
104 @param v pointer to a vector
105 @param length_increment length increment in elements
106 @param data_bytes requested size in bytes
107 @param header_bytes header size in bytes (may be zero)
108 @param data_align alignment (may be zero)
109 @return v_prime pointer to resized vector, may or may not equal v
113 _vec_resize (void * v,
114 word length_increment,
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, header_bytes,
143 clib_max (sizeof (vec_header_t), data_align));
146 /** \brief Predicate function, says whether the supplied vector is a clib heap
147 object (general version).
149 @param v pointer to a vector
150 @param header_bytes vector header size in bytes (may be zero)
153 uword clib_mem_is_vec_h (void * v, uword header_bytes);
156 /** \brief Predicate function, says whether the supplied vector is a clib heap
159 @param v pointer to a vector
162 always_inline uword clib_mem_is_vec (void * v)
163 { return clib_mem_is_vec_h (v, 0); }
165 /* Local variable naming macro (prevents collisions with other macro naming). */
166 #define _v(var) _vec_##var
168 /** \brief Resize a vector (general version).
169 Add N elements to end of given vector V, return pointer to start of vector.
170 Vector will have room for H header bytes and will have user's data aligned
171 at alignment A (rounded to next power of 2).
173 @param V pointer to a vector
174 @param N number of elements to add
175 @param H header size in bytes (may be zero)
176 @param A alignment (may be zero)
177 @return V (value-result macro parameter)
180 #define vec_resize_ha(V,N,H,A) \
183 word _v(l) = vec_len (V); \
184 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
187 /** \brief Resize a vector (no header, unspecified alignment)
188 Add N elements to end of given vector V, return pointer to start of vector.
189 Vector will have room for H header bytes and will have user's data aligned
190 at alignment A (rounded to next power of 2).
192 @param V pointer to a vector
193 @param N number of elements to add
194 @return V (value-result macro parameter)
196 #define vec_resize(V,N) vec_resize_ha(V,N,0,0)
198 /** \brief Resize a vector (no header, alignment specified).
199 Add N elements to end of given vector V, return pointer to start of vector.
200 Vector will have room for H header bytes and will have user's data aligned
201 at alignment A (rounded to next power of 2).
203 @param V pointer to a vector
204 @param N number of elements to add
205 @param A alignment (may be zero)
206 @return V (value-result macro parameter)
209 #define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
211 /** \brief Allocate space for N more elements
213 @param V pointer to a vector
214 @param N number of elements to add
215 @param H header size in bytes (may be zero)
216 @param A alignment (may be zero)
217 @return V (value-result macro parameter)
220 #define vec_alloc_ha(V,N,H,A) \
222 uword _v(l) = vec_len (V); \
223 vec_resize_ha (V, N, H, A); \
224 _vec_len (V) = _v(l); \
227 /** \brief Allocate space for N more elements
228 (no header, unspecified alignment)
230 @param V pointer to a vector
231 @param N number of elements to add
232 @return V (value-result macro parameter)
234 #define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
236 /** \brief Allocate space for N more elements (no header, given alignment)
237 @param V pointer to a vector
238 @param N number of elements to add
239 @param A alignment (may be zero)
240 @return V (value-result macro parameter)
243 #define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
245 /** \brief Create new vector of given type and length (general version).
246 @param T type of elements in new vector
247 @param N number of elements to add
248 @param H header size in bytes (may be zero)
249 @param A alignment (may be zero)
252 #define vec_new_ha(T,N,H,A) \
255 _vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
258 /** \brief Create new vector of given type and length
259 (unspecified alignment, no header).
261 @param T type of elements in new vector
262 @param N number of elements to add
265 #define vec_new(T,N) vec_new_ha(T,N,0,0)
266 /** \brief Create new vector of given type and length
267 (alignment specified, no header).
269 @param T type of elements in new vector
270 @param N number of elements to add
271 @param A alignment (may be zero)
274 #define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
276 /** \brief Free vector's memory (general version)
278 @param V pointer to a vector
279 @param H size of header in bytes
280 @return V (value-result parameter, V=0)
282 #define vec_free_h(V,H) \
286 clib_mem_free (vec_header ((V), (H))); \
291 /** \brief Free vector's memory (no header).
292 @param V pointer to a vector
293 @return V (value-result parameter, V=0)
295 #define vec_free(V) vec_free_h(V,0)
297 /**\brief Free vector user header (syntactic sugar)
298 @param h vector header
301 #define vec_free_header(h) clib_mem_free (h)
303 /** \brief Return copy of vector (general version).
305 @param V pointer to a vector
306 @param H size of header in bytes
307 @param A alignment (may be zero)
309 @return Vdup copy of vector
312 #define vec_dup_ha(V,H,A) \
314 __typeof__ ((V)[0]) * _v(v) = 0; \
315 uword _v(l) = vec_len (V); \
318 vec_resize_ha (_v(v), _v(l), (H), (A)); \
319 memcpy (_v(v), (V), _v(l) * sizeof ((V)[0])); \
324 /** \brief Return copy of vector (no header, no alignment)
326 @param V pointer to a vector
327 @return Vdup copy of vector
329 #define vec_dup(V) vec_dup_ha(V,0,0)
331 /** \brief Return copy of vector (no header, alignment specified).
333 @param V pointer to a vector
334 @param A alignment (may be zero)
336 @return Vdup copy of vector
338 #define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
340 /** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
343 @param DST destination
346 #define vec_copy(DST,SRC) memcpy (DST, SRC, vec_len (DST) * sizeof ((DST)[0]))
348 /** \brief Clone a vector. Make a new vector with the
349 same size as a given vector but possibly with a different type.
351 @param NEW_V pointer to new vector
352 @param OLD_V pointer to old vector
354 #define vec_clone(NEW_V,OLD_V) \
357 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
358 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
361 /** \brief Make sure vector is long enough for given index (general version).
363 @param V (possibly NULL) pointer to a vector.
364 @param I vector index which will be valid upon return
365 @param H header size in bytes (may be zero)
366 @param A alignment (may be zero)
367 @return V (value-result macro parameter)
370 #define vec_validate_ha(V,I,H,A) \
373 word _v(l) = vec_len (V); \
374 if (_v(i) >= _v(l)) \
376 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
377 /* Must zero new space since user may have previously \
378 used e.g. _vec_len (v) -= 10 */ \
379 memset ((V) + _v(l), 0, (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
383 /** \brief Make sure vector is long enough for given index
384 (no header, unspecified alignment)
386 @param V (possibly NULL) pointer to a vector.
387 @param I vector index which will be valid upon return
388 @return V (value-result macro parameter)
390 #define vec_validate(V,I) vec_validate_ha(V,I,0,0)
392 /** \brief Make sure vector is long enough for given index
393 (no header, specified alignment)
395 @param V (possibly NULL) pointer to a vector.
396 @param I vector index which will be valid upon return
397 @param A alignment (may be zero)
398 @return V (value-result macro parameter)
401 #define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
403 /** \brief Make sure vector is long enough for given index
404 and initialize empty space (general version)
406 @param V (possibly NULL) pointer to a vector.
407 @param I vector index which will be valid upon return
408 @param INIT initial value (can be a complex expression!)
409 @param H header size in bytes (may be zero)
410 @param A alignment (may be zero)
411 @return V (value-result macro parameter)
413 #define vec_validate_init_empty_ha(V,I,INIT,H,A) \
416 word _v(l) = vec_len (V); \
417 if (_v(i) >= _v(l)) \
419 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
420 while (_v(l) <= _v(i)) \
422 (V)[_v(l)] = (INIT); \
428 /** \brief Make sure vector is long enough for given index
429 and initialize empty space (no header, unspecified alignment)
431 @param V (possibly NULL) pointer to a vector.
432 @param I vector index which will be valid upon return
433 @param INIT initial value (can be a complex expression!)
434 @param H header size in bytes (may be zero)
435 @param A alignment (may be zero)
436 @return V (value-result macro parameter)
439 #define vec_validate_init_empty(V,I,INIT) \
440 vec_validate_init_empty_ha(V,I,INIT,0,0)
442 /** \brief Make sure vector is long enough for given index
443 and initialize empty space (no header, alignment alignment)
445 @param V (possibly NULL) pointer to a vector.
446 @param I vector index which will be valid upon return
447 @param INIT initial value (can be a complex expression!)
448 @param H header size in bytes (may be zero)
449 @param A alignment (may be zero)
450 @return V (value-result macro parameter)
452 #define vec_validate_init_empty_aligned(V,I,A) \
453 vec_validate_init_empty_ha(V,I,INIT,0,A)
455 /** \brief Add 1 element to end of vector (general version).
457 @param V pointer to a vector
458 @param E element to add
459 @param H header size in bytes (may be zero)
460 @param A alignment (may be zero)
461 @return V (value-result macro parameter)
463 #define vec_add1_ha(V,E,H,A) \
465 word _v(l) = vec_len (V); \
466 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
470 /** \brief Add 1 element to end of vector (unspecified alignment).
472 @param V pointer to a vector
473 @param E element to add
474 @return V (value-result macro parameter)
476 #define vec_add1(V,E) vec_add1_ha(V,E,0,0)
478 /** \brief Add 1 element to end of vector (alignment specified).
480 @param V pointer to a vector
481 @param E element to add
482 @param H header size in bytes (may be zero)
483 @param A alignment (may be zero)
484 @return V (value-result macro parameter)
486 #define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
488 /** \brief Add N elements to end of vector V,
489 return pointer to new elements in P. (general version)
491 @param V pointer to a vector
492 @param P pointer to new vector element(s)
493 @param N number of elements to add
494 @param H header size in bytes (may be zero)
495 @param A alignment (may be zero)
496 @return V and P (value-result macro parameters)
498 #define vec_add2_ha(V,P,N,H,A) \
501 word _v(l) = vec_len (V); \
502 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
506 /** \brief Add N elements to end of vector V,
507 return pointer to new elements in P. (no header, unspecified alignment)
509 @param V pointer to a vector
510 @param P pointer to new vector element(s)
511 @param N number of elements to add
512 @return V and P (value-result macro parameters)
515 #define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
517 /** \brief Add N elements to end of vector V,
518 return pointer to new elements in P. (no header, alignment specified)
520 @param V pointer to a vector
521 @param P pointer to new vector element(s)
522 @param N number of elements to add
523 @param A alignment (may be zero)
524 @return V and P (value-result macro parameters)
527 #define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
529 /** \brief Add N elements to end of vector V (general version)
531 @param V pointer to a vector
532 @param E pointer to element(s) to add
533 @param N number of elements to add
534 @param H header size in bytes (may be zero)
535 @param A alignment (may be zero)
536 @return V (value-result macro parameter)
538 #define vec_add_ha(V,E,N,H,A) \
541 word _v(l) = vec_len (V); \
542 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
543 memcpy ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
546 /** \brief Add N elements to end of vector V (no header, unspecified alignment)
548 @param V pointer to a vector
549 @param E pointer to element(s) to add
550 @param N number of elements to add
551 @return V (value-result macro parameter)
553 #define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
555 /** \brief Add N elements to end of vector V (no header, specified alignment)
557 @param V pointer to a vector
558 @param E pointer to element(s) to add
559 @param N number of elements to add
560 @param A alignment (may be zero)
561 @return V (value-result macro parameter)
563 #define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
565 /** \brief Returns last element of a vector and decrements its length
567 @param V pointer to a vector
568 @return E element removed from the end of the vector
572 uword _v(l) = vec_len (V); \
573 ASSERT (_v(l) > 0); \
575 _vec_len (V) = _v (l); \
579 /** \brief Set E to the last element of a vector, decrement vector length
580 @param V pointer to a vector
581 @param E pointer to the last vector element
582 @return E element removed from the end of the vector
583 (value-result macro parameter
586 #define vec_pop2(V,E) \
588 uword _v(l) = vec_len (V); \
589 if (_v(l) > 0) (E) = vec_pop (V); \
593 /** \brief Insert N vector elements starting at element M,
594 initialize new elements (general version).
596 @param V (possibly NULL) pointer to a vector.
597 @param N number of elements to insert
598 @param M insertion point
599 @param INIT initial value (can be a complex expression!)
600 @param H header size in bytes (may be zero)
601 @param A alignment (may be zero)
602 @return V (value-result macro parameter)
604 #define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
606 word _v(l) = vec_len (V); \
609 V = _vec_resize ((V), \
611 (_v(l) + _v(n))*sizeof((V)[0]), \
613 ASSERT (_v(m) <= _v(l)); \
614 memmove ((V) + _v(m) + _v(n), \
616 (_v(l) - _v(m)) * sizeof ((V)[0])); \
617 memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
620 /** \brief Insert N vector elements starting at element M,
621 initialize new elements to zero (general version)
623 @param V (possibly NULL) pointer to a vector.
624 @param N number of elements to insert
625 @param M insertion point
626 @param H header size in bytes (may be zero)
627 @param A alignment (may be zero)
628 @return V (value-result macro parameter)
630 #define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
632 /** \brief Insert N vector elements starting at element M,
633 initialize new elements to zero (no header, unspecified alignment)
635 @param V (possibly NULL) pointer to a vector.
636 @param N number of elements to insert
637 @param M insertion point
638 @return V (value-result macro parameter)
640 #define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
642 /** \brief Insert N vector elements starting at element M,
643 initialize new elements to zero (no header, alignment specified)
645 @param V (possibly NULL) pointer to a vector.
646 @param N number of elements to insert
647 @param M insertion point
648 @param A alignment (may be zero)
649 @return V (value-result macro parameter)
651 #define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
653 /** \brief Insert N vector elements starting at element M,
654 initialize new elements (no header, unspecified alignment)
656 @param V (possibly NULL) pointer to a vector.
657 @param N number of elements to insert
658 @param M insertion point
659 @param INIT initial value (can be a complex expression!)
660 @return V (value-result macro parameter)
663 #define vec_insert_init_empty(V,N,M,INIT) \
664 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
665 /* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
667 /** \brief Insert N vector elements starting at element M,
668 initialize new elements (no header, specified alignment)
670 @param V (possibly NULL) pointer to a vector.
671 @param N number of elements to insert
672 @param M insertion point
673 @param INIT initial value (can be a complex expression!)
674 @param A alignment (may be zero)
675 @return V (value-result macro parameter)
677 #define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
678 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
680 /** \brief Insert N vector elements starting at element M,
681 insert given elements (general version)
683 @param V (possibly NULL) pointer to a vector.
684 @param E element(s) to insert
685 @param N number of elements to insert
686 @param M insertion point
687 @param H header size in bytes (may be zero)
688 @param A alignment (may be zero)
689 @return V (value-result macro parameter)
692 #define vec_insert_elts_ha(V,E,N,M,H,A) \
694 word _v(l) = vec_len (V); \
697 V = _vec_resize ((V), \
699 (_v(l) + _v(n))*sizeof((V)[0]), \
701 ASSERT (_v(m) <= _v(l)); \
702 memmove ((V) + _v(m) + _v(n), \
704 (_v(l) - _v(m)) * sizeof ((V)[0])); \
705 memcpy ((V) + _v(m), (E), _v(n) * sizeof ((V)[0])); \
708 /** \brief Insert N vector elements starting at element M,
709 insert given elements (no header, unspecified alignment)
711 @param V (possibly NULL) pointer to a vector.
712 @param E element(s) to insert
713 @param N number of elements to insert
714 @param M insertion point
715 @return V (value-result macro parameter)
717 #define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
719 /** \brief Insert N vector elements starting at element M,
720 insert given elements (no header, specified alignment)
722 @param V (possibly NULL) pointer to a vector.
723 @param E element(s) to insert
724 @param N number of elements to insert
725 @param M insertion point
726 @param A alignment (may be zero)
727 @return V (value-result macro parameter)
729 #define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
731 /** \brief Delete N elements starting at element M
733 @param V pointer to a vector
734 @param N number of elements to delete
735 @param M first element to delete
736 @return V (value-result macro parameter)
738 #define vec_delete(V,N,M) \
740 word _v(l) = vec_len (V); \
743 /* Copy over deleted elements. */ \
744 if (_v(l) - _v(n) - _v(m) > 0) \
745 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
746 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
747 /* Zero empty space at end (for future re-allocation). */ \
749 memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
750 _vec_len (V) -= _v(n); \
753 /** \brief Delete the element at index I
755 @param V pointer to a vector
756 @param I index to delete
758 #define vec_del1(v,i) \
760 uword _vec_del_l = _vec_len (v) - 1; \
761 uword _vec_del_i = (i); \
762 if (_vec_del_i < _vec_del_l) \
763 (v)[_vec_del_i] = (v)[_vec_del_l]; \
764 _vec_len (v) = _vec_del_l; \
767 /** \brief Append v2 after v1. Result in v1.
768 @param V1 target vector
769 @param V2 vector to append
772 #define vec_append(v1,v2) \
774 uword _v(l1) = vec_len (v1); \
775 uword _v(l2) = vec_len (v2); \
777 v1 = _vec_resize ((v1), _v(l2), \
778 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
779 memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
782 /** \brief Append v2 after v1. Result in v1. Specified alignment.
783 @param V1 target vector
784 @param V2 vector to append
785 @param align required alignment
788 #define vec_append_aligned(v1,v2,align) \
790 uword _v(l1) = vec_len (v1); \
791 uword _v(l2) = vec_len (v2); \
793 v1 = _vec_resize ((v1), _v(l2), \
794 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
795 memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
798 /** \brief Prepend v2 before v1. Result in v1.
799 @param V1 target vector
800 @param V2 vector to prepend
803 #define vec_prepend(v1,v2) \
805 uword _v(l1) = vec_len (v1); \
806 uword _v(l2) = vec_len (v2); \
808 v1 = _vec_resize ((v1), _v(l2), \
809 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
810 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
811 memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
814 /** \brief Prepend v2 before v1. Result in v1. Specified alignment
815 @param V1 target vector
816 @param V2 vector to prepend
817 @param align required alignment
820 #define vec_prepend_aligned(v1,v2,align) \
822 uword _v(l1) = vec_len (v1); \
823 uword _v(l2) = vec_len (v2); \
825 v1 = _vec_resize ((v1), _v(l2), \
826 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
827 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
828 memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
832 /** \brief Zero all vector elements. Null-pointer tolerant.
833 @param var Vector to zero
835 #define vec_zero(var) \
838 memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
841 /** \brief Set all vector elements to given value. Null-pointer tolerant.
842 @param v vector to set
843 @param val value for each vector element
845 #define vec_set(v,val) \
848 __typeof__ ((v)[0]) _val = (val); \
849 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
854 #include <stdlib.h> /* for qsort */
857 /** \brief Compare two vectors, not NULL-pointer tolerant
859 @param v1 Pointer to a vector
860 @param v2 Pointer to a vector
861 @return 1 if equal, 0 if unequal
863 #define vec_is_equal(v1,v2) \
864 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
866 /** \brief Compare two vectors (only applicable to vectors of signed numbers).
867 Used in qsort compare functions.
869 @param v1 Pointer to a vector
870 @param v2 Pointer to a vector
873 #define vec_cmp(v1,v2) \
875 word _v(i), _v(cmp), _v(l); \
876 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
878 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
879 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
883 if (_v(cmp) == 0 && _v(l) > 0) \
884 _v(cmp) = vec_len(v1) - vec_len(v2); \
885 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
888 /**\brief Sort a vector with qsort via user's comparison body
890 Example to sort an integer vector:
892 vec_sort (int_vec, i0, i1, i0[0] - i1[0]);
894 WARNING: vec_sort requires an executable stack segment.
895 If at all possible, use vec_sort_with_function () instead.
897 @param vec vector to sort
898 @param v0 vector element
899 @param v1 vector element
900 @param body vector comparision expression
903 #define vec_sort(vec,v0,v1,body) \
905 int _vec_sort_compare (const void * _v0, \
908 __typeof__ (vec) v0 = (__typeof__ (vec)) _v0; \
909 __typeof__ (vec) v1 = (__typeof__ (vec)) _v1; \
910 return (int) (body); \
912 qsort (vec, vec_len (vec), sizeof (vec[0]), _vec_sort_compare); \
915 /** \brief Sort a vector using the supplied element comparison function
917 @param vec vector to sort
918 @param f comparison function
920 #define vec_sort_with_function(vec,f) \
922 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
925 /** \brief Make a vector containing a NULL terminated c-string.
927 @param V (possibly NULL) pointer to a vector.
928 @param S pointer to string buffer.
929 @param L string length (NOT including the terminating NULL; a la strlen())
931 #define vec_validate_init_c_string(V, S, L) \
933 vec_reset_length (V); \
934 vec_validate ((V), (L)); \
936 memcpy ((V), (S), (L)); \
943 @param V (possibly NULL) pointer to a vector.
944 @return BOOLEAN indicating if the vector c-string is null terminated.
946 #define vec_c_string_is_terminated(V) \
947 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
949 /** \brief (If necessary) Null terminate a vector containing a c-string.
951 @param V (possibly NULL) pointer to a vector.
952 @return V (value-result macro parameter)
954 #define vec_terminate_c_string(V) \
956 u32 vl = vec_len ((V)); \
957 if (!vec_c_string_is_terminated(V)) \
959 vec_validate ((V), vl); \
964 #endif /* included_vec_h */