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,
105 /** \brief Low-level vector resize function, usually not called directly
107 @param v pointer to a vector
108 @param length_increment length increment in elements
109 @param data_bytes requested size in bytes
110 @param header_bytes header size in bytes (may be zero)
111 @param data_align alignment (may be zero)
112 @return v_prime pointer to resized vector, may or may not equal v
116 _vec_resize (void * v,
117 word length_increment,
122 vec_header_t * vh = _vec_find (v);
123 uword new_data_bytes, aligned_header_bytes;
125 aligned_header_bytes = vec_header_bytes (header_bytes);
127 new_data_bytes = data_bytes + aligned_header_bytes;
129 if (PREDICT_TRUE (v != 0))
131 void * p = v - aligned_header_bytes;
133 /* Vector header must start heap object. */
134 ASSERT (clib_mem_is_heap_object (p));
136 /* Typically we'll not need to resize. */
137 if (new_data_bytes <= clib_mem_size (p))
139 vh->len += length_increment;
144 /* Slow path: call helper function. */
145 return vec_resize_allocate_memory (v, length_increment, data_bytes, header_bytes,
146 clib_max (sizeof (vec_header_t), data_align));
149 /** \brief Predicate function, says whether the supplied vector is a clib heap
150 object (general version).
152 @param v pointer to a vector
153 @param header_bytes vector header size in bytes (may be zero)
156 uword clib_mem_is_vec_h (void * v, uword header_bytes);
159 /** \brief Predicate function, says whether the supplied vector is a clib heap
162 @param v pointer to a vector
165 always_inline uword clib_mem_is_vec (void * v)
166 { return clib_mem_is_vec_h (v, 0); }
168 /* Local variable naming macro (prevents collisions with other macro naming). */
169 #define _v(var) _vec_##var
171 /** \brief Resize a vector (general version).
172 Add N elements to end of given vector V, return pointer to start of vector.
173 Vector will have room for H header bytes and will have user's data aligned
174 at alignment A (rounded to next power of 2).
176 @param V pointer to a vector
177 @param N number of elements to add
178 @param H header size in bytes (may be zero)
179 @param A alignment (may be zero)
180 @return V (value-result macro parameter)
183 #define vec_resize_ha(V,N,H,A) \
186 word _v(l) = vec_len (V); \
187 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
190 /** \brief Resize a vector (no header, unspecified alignment)
191 Add N elements to end of given vector V, return pointer to start of vector.
192 Vector will have room for H header bytes and will have user's data aligned
193 at alignment A (rounded to next power of 2).
195 @param V pointer to a vector
196 @param N number of elements to add
197 @return V (value-result macro parameter)
199 #define vec_resize(V,N) vec_resize_ha(V,N,0,0)
201 /** \brief Resize a vector (no header, alignment specified).
202 Add N elements to end of given vector V, return pointer to start of vector.
203 Vector will have room for H header bytes and will have user's data aligned
204 at alignment A (rounded to next power of 2).
206 @param V pointer to a vector
207 @param N number of elements to add
208 @param A alignment (may be zero)
209 @return V (value-result macro parameter)
212 #define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
214 /** \brief Allocate space for N more elements
216 @param V pointer to a vector
217 @param N number of elements to add
218 @param H header size in bytes (may be zero)
219 @param A alignment (may be zero)
220 @return V (value-result macro parameter)
223 #define vec_alloc_ha(V,N,H,A) \
225 uword _v(l) = vec_len (V); \
226 vec_resize_ha (V, N, H, A); \
227 _vec_len (V) = _v(l); \
230 /** \brief Allocate space for N more elements
231 (no header, unspecified alignment)
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_alloc(V,N) vec_alloc_ha(V,N,0,0)
239 /** \brief Allocate space for N more elements (no header, given alignment)
240 @param V pointer to a vector
241 @param N number of elements to add
242 @param A alignment (may be zero)
243 @return V (value-result macro parameter)
246 #define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
248 /** \brief Create new vector of given type and length (general version).
249 @param T type of elements in new vector
250 @param N number of elements to add
251 @param H header size in bytes (may be zero)
252 @param A alignment (may be zero)
255 #define vec_new_ha(T,N,H,A) \
258 _vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
261 /** \brief Create new vector of given type and length
262 (unspecified alignment, no header).
264 @param T type of elements in new vector
265 @param N number of elements to add
268 #define vec_new(T,N) vec_new_ha(T,N,0,0)
269 /** \brief Create new vector of given type and length
270 (alignment specified, no header).
272 @param T type of elements in new vector
273 @param N number of elements to add
274 @param A alignment (may be zero)
277 #define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
279 /** \brief Free vector's memory (general version)
281 @param V pointer to a vector
282 @param H size of header in bytes
283 @return V (value-result parameter, V=0)
285 #define vec_free_h(V,H) \
289 clib_mem_free (vec_header ((V), (H))); \
294 /** \brief Free vector's memory (no header).
295 @param V pointer to a vector
296 @return V (value-result parameter, V=0)
298 #define vec_free(V) vec_free_h(V,0)
300 /**\brief Free vector user header (syntactic sugar)
301 @param h vector header
304 #define vec_free_header(h) clib_mem_free (h)
306 /** \brief Return copy of vector (general version).
308 @param V pointer to a vector
309 @param H size of header in bytes
310 @param A alignment (may be zero)
312 @return Vdup copy of vector
315 #define vec_dup_ha(V,H,A) \
317 __typeof__ ((V)[0]) * _v(v) = 0; \
318 uword _v(l) = vec_len (V); \
321 vec_resize_ha (_v(v), _v(l), (H), (A)); \
322 memcpy (_v(v), (V), _v(l) * sizeof ((V)[0])); \
327 /** \brief Return copy of vector (no header, no alignment)
329 @param V pointer to a vector
330 @return Vdup copy of vector
332 #define vec_dup(V) vec_dup_ha(V,0,0)
334 /** \brief Return copy of vector (no header, alignment specified).
336 @param V pointer to a vector
337 @param A alignment (may be zero)
339 @return Vdup copy of vector
341 #define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
343 /** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
346 @param DST destination
349 #define vec_copy(DST,SRC) memcpy (DST, SRC, vec_len (DST) * sizeof ((DST)[0]))
351 /** \brief Clone a vector. Make a new vector with the
352 same size as a given vector but possibly with a different type.
354 @param NEW_V pointer to new vector
355 @param OLD_V pointer to old vector
357 #define vec_clone(NEW_V,OLD_V) \
360 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
361 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
364 /** \brief Make sure vector is long enough for given index (general version).
366 @param V (possibly NULL) pointer to a vector.
367 @param I vector index which will be valid upon return
368 @param H header size in bytes (may be zero)
369 @param A alignment (may be zero)
370 @return V (value-result macro parameter)
373 #define vec_validate_ha(V,I,H,A) \
376 word _v(l) = vec_len (V); \
377 if (_v(i) >= _v(l)) \
379 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
380 /* Must zero new space since user may have previously \
381 used e.g. _vec_len (v) -= 10 */ \
382 memset ((V) + _v(l), 0, (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
386 /** \brief Make sure vector is long enough for given index
387 (no header, unspecified alignment)
389 @param V (possibly NULL) pointer to a vector.
390 @param I vector index which will be valid upon return
391 @return V (value-result macro parameter)
393 #define vec_validate(V,I) vec_validate_ha(V,I,0,0)
395 /** \brief Make sure vector is long enough for given index
396 (no header, specified alignment)
398 @param V (possibly NULL) pointer to a vector.
399 @param I vector index which will be valid upon return
400 @param A alignment (may be zero)
401 @return V (value-result macro parameter)
404 #define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
406 /** \brief Make sure vector is long enough for given index
407 and initialize empty space (general version)
409 @param V (possibly NULL) pointer to a vector.
410 @param I vector index which will be valid upon return
411 @param INIT initial value (can be a complex expression!)
412 @param H header size in bytes (may be zero)
413 @param A alignment (may be zero)
414 @return V (value-result macro parameter)
416 #define vec_validate_init_empty_ha(V,I,INIT,H,A) \
419 word _v(l) = vec_len (V); \
420 if (_v(i) >= _v(l)) \
422 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
423 while (_v(l) <= _v(i)) \
425 (V)[_v(l)] = (INIT); \
431 /** \brief Make sure vector is long enough for given index
432 and initialize empty space (no header, unspecified alignment)
434 @param V (possibly NULL) pointer to a vector.
435 @param I vector index which will be valid upon return
436 @param INIT initial value (can be a complex expression!)
437 @param H header size in bytes (may be zero)
438 @param A alignment (may be zero)
439 @return V (value-result macro parameter)
442 #define vec_validate_init_empty(V,I,INIT) \
443 vec_validate_init_empty_ha(V,I,INIT,0,0)
445 /** \brief Make sure vector is long enough for given index
446 and initialize empty space (no header, alignment alignment)
448 @param V (possibly NULL) pointer to a vector.
449 @param I vector index which will be valid upon return
450 @param INIT initial value (can be a complex expression!)
451 @param H header size in bytes (may be zero)
452 @param A alignment (may be zero)
453 @return V (value-result macro parameter)
455 #define vec_validate_init_empty_aligned(V,I,A) \
456 vec_validate_init_empty_ha(V,I,INIT,0,A)
458 /** \brief Add 1 element to end of vector (general version).
460 @param V pointer to a vector
461 @param E element to add
462 @param H header size in bytes (may be zero)
463 @param A alignment (may be zero)
464 @return V (value-result macro parameter)
466 #define vec_add1_ha(V,E,H,A) \
468 word _v(l) = vec_len (V); \
469 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
473 /** \brief Add 1 element to end of vector (unspecified alignment).
475 @param V pointer to a vector
476 @param E element to add
477 @return V (value-result macro parameter)
479 #define vec_add1(V,E) vec_add1_ha(V,E,0,0)
481 /** \brief Add 1 element to end of vector (alignment specified).
483 @param V pointer to a vector
484 @param E element to add
485 @param H header size in bytes (may be zero)
486 @param A alignment (may be zero)
487 @return V (value-result macro parameter)
489 #define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
491 /** \brief Add N elements to end of vector V,
492 return pointer to new elements in P. (general version)
494 @param V pointer to a vector
495 @param P pointer to new vector element(s)
496 @param N number of elements to add
497 @param H header size in bytes (may be zero)
498 @param A alignment (may be zero)
499 @return V and P (value-result macro parameters)
501 #define vec_add2_ha(V,P,N,H,A) \
504 word _v(l) = vec_len (V); \
505 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
509 /** \brief Add N elements to end of vector V,
510 return pointer to new elements in P. (no header, unspecified alignment)
512 @param V pointer to a vector
513 @param P pointer to new vector element(s)
514 @param N number of elements to add
515 @return V and P (value-result macro parameters)
518 #define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
520 /** \brief Add N elements to end of vector V,
521 return pointer to new elements in P. (no header, alignment specified)
523 @param V pointer to a vector
524 @param P pointer to new vector element(s)
525 @param N number of elements to add
526 @param A alignment (may be zero)
527 @return V and P (value-result macro parameters)
530 #define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
532 /** \brief Add N elements to end of vector V (general version)
534 @param V pointer to a vector
535 @param E pointer to element(s) to add
536 @param N number of elements to add
537 @param H header size in bytes (may be zero)
538 @param A alignment (may be zero)
539 @return V (value-result macro parameter)
541 #define vec_add_ha(V,E,N,H,A) \
544 word _v(l) = vec_len (V); \
545 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
546 memcpy ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
549 /** \brief Add N elements to end of vector V (no header, unspecified alignment)
551 @param V pointer to a vector
552 @param E pointer to element(s) to add
553 @param N number of elements to add
554 @return V (value-result macro parameter)
556 #define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
558 /** \brief Add N elements to end of vector V (no header, specified alignment)
560 @param V pointer to a vector
561 @param E pointer to element(s) to add
562 @param N number of elements to add
563 @param A alignment (may be zero)
564 @return V (value-result macro parameter)
566 #define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
568 /** \brief Returns last element of a vector and decrements its length
570 @param V pointer to a vector
571 @return E element removed from the end of the vector
575 uword _v(l) = vec_len (V); \
576 ASSERT (_v(l) > 0); \
578 _vec_len (V) = _v (l); \
582 /** \brief Set E to the last element of a vector, decrement vector length
583 @param V pointer to a vector
584 @param E pointer to the last vector element
585 @return E element removed from the end of the vector
586 (value-result macro parameter
589 #define vec_pop2(V,E) \
591 uword _v(l) = vec_len (V); \
592 if (_v(l) > 0) (E) = vec_pop (V); \
596 /** \brief Insert N vector elements starting at element M,
597 initialize new elements (general version).
599 @param V (possibly NULL) pointer to a vector.
600 @param N number of elements to insert
601 @param M insertion point
602 @param INIT initial value (can be a complex expression!)
603 @param H header size in bytes (may be zero)
604 @param A alignment (may be zero)
605 @return V (value-result macro parameter)
607 #define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
609 word _v(l) = vec_len (V); \
612 V = _vec_resize ((V), \
614 (_v(l) + _v(n))*sizeof((V)[0]), \
616 ASSERT (_v(m) <= _v(l)); \
617 memmove ((V) + _v(m) + _v(n), \
619 (_v(l) - _v(m)) * sizeof ((V)[0])); \
620 memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
623 /** \brief Insert N vector elements starting at element M,
624 initialize new elements to zero (general version)
626 @param V (possibly NULL) pointer to a vector.
627 @param N number of elements to insert
628 @param M insertion point
629 @param H header size in bytes (may be zero)
630 @param A alignment (may be zero)
631 @return V (value-result macro parameter)
633 #define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
635 /** \brief Insert N vector elements starting at element M,
636 initialize new elements to zero (no header, unspecified alignment)
638 @param V (possibly NULL) pointer to a vector.
639 @param N number of elements to insert
640 @param M insertion point
641 @return V (value-result macro parameter)
643 #define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
645 /** \brief Insert N vector elements starting at element M,
646 initialize new elements to zero (no header, alignment specified)
648 @param V (possibly NULL) pointer to a vector.
649 @param N number of elements to insert
650 @param M insertion point
651 @param A alignment (may be zero)
652 @return V (value-result macro parameter)
654 #define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
656 /** \brief Insert N vector elements starting at element M,
657 initialize new elements (no header, unspecified alignment)
659 @param V (possibly NULL) pointer to a vector.
660 @param N number of elements to insert
661 @param M insertion point
662 @param INIT initial value (can be a complex expression!)
663 @return V (value-result macro parameter)
666 #define vec_insert_init_empty(V,N,M,INIT) \
667 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
668 /* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
670 /** \brief Insert N vector elements starting at element M,
671 initialize new elements (no header, specified alignment)
673 @param V (possibly NULL) pointer to a vector.
674 @param N number of elements to insert
675 @param M insertion point
676 @param INIT initial value (can be a complex expression!)
677 @param A alignment (may be zero)
678 @return V (value-result macro parameter)
680 #define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
681 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
683 /** \brief Insert N vector elements starting at element M,
684 insert given elements (general version)
686 @param V (possibly NULL) pointer to a vector.
687 @param E element(s) to insert
688 @param N number of elements to insert
689 @param M insertion point
690 @param H header size in bytes (may be zero)
691 @param A alignment (may be zero)
692 @return V (value-result macro parameter)
695 #define vec_insert_elts_ha(V,E,N,M,H,A) \
697 word _v(l) = vec_len (V); \
700 V = _vec_resize ((V), \
702 (_v(l) + _v(n))*sizeof((V)[0]), \
704 ASSERT (_v(m) <= _v(l)); \
705 memmove ((V) + _v(m) + _v(n), \
707 (_v(l) - _v(m)) * sizeof ((V)[0])); \
708 memcpy ((V) + _v(m), (E), _v(n) * sizeof ((V)[0])); \
711 /** \brief Insert N vector elements starting at element M,
712 insert given elements (no header, unspecified alignment)
714 @param V (possibly NULL) pointer to a vector.
715 @param E element(s) to insert
716 @param N number of elements to insert
717 @param M insertion point
718 @return V (value-result macro parameter)
720 #define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
722 /** \brief Insert N vector elements starting at element M,
723 insert given elements (no header, specified alignment)
725 @param V (possibly NULL) pointer to a vector.
726 @param E element(s) to insert
727 @param N number of elements to insert
728 @param M insertion point
729 @param A alignment (may be zero)
730 @return V (value-result macro parameter)
732 #define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
734 /** \brief Delete N elements starting at element M
736 @param V pointer to a vector
737 @param N number of elements to delete
738 @param M first element to delete
739 @return V (value-result macro parameter)
741 #define vec_delete(V,N,M) \
743 word _v(l) = vec_len (V); \
746 /* Copy over deleted elements. */ \
747 if (_v(l) - _v(n) - _v(m) > 0) \
748 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
749 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
750 /* Zero empty space at end (for future re-allocation). */ \
752 memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
753 _vec_len (V) -= _v(n); \
756 /** \brief Delete the element at index I
758 @param V pointer to a vector
759 @param I index to delete
761 #define vec_del1(v,i) \
763 uword _vec_del_l = _vec_len (v) - 1; \
764 uword _vec_del_i = (i); \
765 if (_vec_del_i < _vec_del_l) \
766 (v)[_vec_del_i] = (v)[_vec_del_l]; \
767 _vec_len (v) = _vec_del_l; \
770 /** \brief Append v2 after v1. Result in v1.
771 @param V1 target vector
772 @param V2 vector to append
775 #define vec_append(v1,v2) \
777 uword _v(l1) = vec_len (v1); \
778 uword _v(l2) = vec_len (v2); \
780 v1 = _vec_resize ((v1), _v(l2), \
781 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
782 memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
785 /** \brief Append v2 after v1. Result in v1. Specified alignment.
786 @param V1 target vector
787 @param V2 vector to append
788 @param align required alignment
791 #define vec_append_aligned(v1,v2,align) \
793 uword _v(l1) = vec_len (v1); \
794 uword _v(l2) = vec_len (v2); \
796 v1 = _vec_resize ((v1), _v(l2), \
797 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
798 memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
801 /** \brief Prepend v2 before v1. Result in v1.
802 @param V1 target vector
803 @param V2 vector to prepend
806 #define vec_prepend(v1,v2) \
808 uword _v(l1) = vec_len (v1); \
809 uword _v(l2) = vec_len (v2); \
811 v1 = _vec_resize ((v1), _v(l2), \
812 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
813 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
814 memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
817 /** \brief Prepend v2 before v1. Result in v1. Specified alignment
818 @param V1 target vector
819 @param V2 vector to prepend
820 @param align required alignment
823 #define vec_prepend_aligned(v1,v2,align) \
825 uword _v(l1) = vec_len (v1); \
826 uword _v(l2) = vec_len (v2); \
828 v1 = _vec_resize ((v1), _v(l2), \
829 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
830 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
831 memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
835 /** \brief Zero all vector elements. Null-pointer tolerant.
836 @param var Vector to zero
838 #define vec_zero(var) \
841 memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
844 /** \brief Set all vector elements to given value. Null-pointer tolerant.
845 @param v vector to set
846 @param val value for each vector element
848 #define vec_set(v,val) \
851 __typeof__ ((v)[0]) _val = (val); \
852 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
857 #include <stdlib.h> /* for qsort */
860 /** \brief Compare two vectors, not NULL-pointer tolerant
862 @param v1 Pointer to a vector
863 @param v2 Pointer to a vector
864 @return 1 if equal, 0 if unequal
866 #define vec_is_equal(v1,v2) \
867 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
869 /** \brief Compare two vectors (only applicable to vectors of signed numbers).
870 Used in qsort compare functions.
872 @param v1 Pointer to a vector
873 @param v2 Pointer to a vector
876 #define vec_cmp(v1,v2) \
878 word _v(i), _v(cmp), _v(l); \
879 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
881 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
882 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
886 if (_v(cmp) == 0 && _v(l) > 0) \
887 _v(cmp) = vec_len(v1) - vec_len(v2); \
888 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
891 /**\brief Sort a vector with qsort via user's comparison body
893 Example to sort an integer vector:
895 vec_sort (int_vec, i0, i1, i0[0] - i1[0]);
897 WARNING: vec_sort requires an executable stack segment.
898 If at all possible, use vec_sort_with_function () instead.
900 @param vec vector to sort
901 @param v0 vector element
902 @param v1 vector element
903 @param body vector comparision expression
906 #define vec_sort(vec,v0,v1,body) \
908 int _vec_sort_compare (const void * _v0, \
911 __typeof__ (vec) v0 = (__typeof__ (vec)) _v0; \
912 __typeof__ (vec) v1 = (__typeof__ (vec)) _v1; \
913 return (int) (body); \
915 qsort (vec, vec_len (vec), sizeof (vec[0]), _vec_sort_compare); \
918 /** \brief Sort a vector using the supplied element comparison function
920 @param vec vector to sort
921 @param f comparison function
923 #define vec_sort_with_function(vec,f) \
925 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
928 /** \brief Make a vector containing a NULL terminated c-string.
930 @param V (possibly NULL) pointer to a vector.
931 @param S pointer to string buffer.
932 @param L string length (NOT including the terminating NULL; a la strlen())
934 #define vec_validate_init_c_string(V, S, L) \
936 vec_reset_length (V); \
937 vec_validate ((V), (L)); \
939 memcpy ((V), (S), (L)); \
946 @param V (possibly NULL) pointer to a vector.
947 @return BOOLEAN indicating if the vector c-string is null terminated.
949 #define vec_c_string_is_terminated(V) \
950 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
952 /** \brief (If necessary) Null terminate a vector containing a c-string.
954 @param V (possibly NULL) pointer to a vector.
955 @return V (value-result macro parameter)
957 #define vec_terminate_c_string(V) \
959 u32 vl = vec_len ((V)); \
960 if (!vec_c_string_is_terminated(V)) \
962 vec_validate ((V), vl); \
967 #endif /* included_vec_h */