vppinfra: add option to use libexecinfo
[vpp.git] / src / vppinfra / vec.h
1 /*
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:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 /*
16   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
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:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
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.
36 */
37
38 #ifndef included_vec_h
39 #define included_vec_h
40
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>
45
46 /** \file
47
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.
51
52    The memory layout looks like this:
53
54 ~~~~~~~~
55                     user header (aligned to uword boundary)
56                     vector length: number of elements
57    user's pointer-> vector element #0
58                     vector element #1
59                     ...
60 ~~~~~~~~
61
62    The user pointer contains the address of vector element # 0.  Null
63    pointer vectors are valid and mean a zero length vector.
64
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.
69
70    Typically, the header is not present.  Headers allow for other
71    data structures to be built atop CLIB vectors.
72
73    Users may specify the alignment for first data element of a vector
74    via the vec_*_aligned macros.
75
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,
78    pool, etc.).
79
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.
85
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
89    which are invariant.
90  */
91
92 /** \brief Low-level resize allocation function, usually not called directly
93
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
101 */
102 void *vec_resize_allocate_memory (void *v,
103                                   word length_increment,
104                                   uword data_bytes,
105                                   uword header_bytes, uword data_align,
106                                   uword numa_id);
107
108 /** \brief Low-level vector resize function, usually not called directly
109
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
117 */
118
119 #define _vec_resize_numa(V,L,DB,HB,A,S)                                 \
120 ({                                                                      \
121   __typeof__ ((V)) _V;                                                  \
122   _V = _vec_resize_inline((void *)V,L,DB,HB,clib_max((__alignof__((V)[0])),(A)),(S)); \
123   _V;                                                                   \
124 })
125
126 #define _vec_resize(V,L,DB,HB,A)  \
127   _vec_resize_numa(V,L,DB,HB,A,VEC_NUMA_UNSPECIFIED)
128
129 always_inline void *
130 _vec_resize_inline (void *v,
131                     word length_increment,
132                     uword data_bytes, uword header_bytes, uword data_align,
133                     uword numa_id)
134 {
135   vec_header_t *vh = _vec_find (v);
136   uword new_data_bytes, aligned_header_bytes;
137   void *oldheap;
138
139   aligned_header_bytes = vec_header_bytes (header_bytes);
140
141   new_data_bytes = data_bytes + aligned_header_bytes;
142
143   if (PREDICT_TRUE (v != 0))
144     {
145       void *p = v - aligned_header_bytes;
146
147       if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
148         {
149           oldheap = clib_mem_get_per_cpu_heap ();
150           clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap (numa_id));
151         }
152
153       /* Vector header must start heap object. */
154       ASSERT (clib_mem_is_heap_object (p));
155
156       /* Typically we'll not need to resize. */
157       if (new_data_bytes <= clib_mem_size (p))
158         {
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);
163           return v;
164         }
165       if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
166         clib_mem_set_per_cpu_heap (oldheap);
167     }
168
169   /* Slow path: call helper function. */
170   return vec_resize_allocate_memory (v, length_increment, data_bytes,
171                                      header_bytes,
172                                      clib_max (sizeof (vec_header_t),
173                                                data_align), numa_id);
174 }
175
176 /** \brief Determine if vector will resize with next allocation
177
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
184 */
185
186 always_inline int
187 _vec_resize_will_expand (void *v,
188                          word length_increment,
189                          uword data_bytes, uword header_bytes,
190                          uword data_align)
191 {
192   uword new_data_bytes, aligned_header_bytes;
193
194   aligned_header_bytes = vec_header_bytes (header_bytes);
195
196   new_data_bytes = data_bytes + aligned_header_bytes;
197
198   if (PREDICT_TRUE (v != 0))
199     {
200       void *p = v - aligned_header_bytes;
201
202       /* Vector header must start heap object. */
203       ASSERT (clib_mem_is_heap_object (p));
204
205       /* Typically we'll not need to resize. */
206       if (new_data_bytes <= clib_mem_size (p))
207         return 0;
208     }
209   return 1;
210 }
211
212 /** \brief Determine if vector will resize with next allocation
213
214     @param V pointer to a vector
215     @param N number of elements to add
216     @return 1 if vector will resize 0 otherwise
217 */
218
219 #define vec_resize_will_expand(V, N)                                          \
220   ({                                                                          \
221     word _v (n) = (N);                                                        \
222     word _v (l) = vec_len (V);                                                \
223     _vec_resize_will_expand ((V), _v (n),                                     \
224                              (_v (l) + _v (n)) * sizeof ((V)[0]), 0, 0);      \
225   })
226
227 /** \brief Predicate function, says whether the supplied vector is a clib heap
228     object (general version).
229
230     @param v pointer to a vector
231     @param header_bytes vector header size in bytes (may be zero)
232     @return 0 or 1
233 */
234 uword clib_mem_is_vec_h (void *v, uword header_bytes);
235
236
237 /** \brief Predicate function, says whether the supplied vector is a clib heap
238     object
239
240     @param v pointer to a vector
241     @return 0 or 1
242 */
243 always_inline uword
244 clib_mem_is_vec (void *v)
245 {
246   return clib_mem_is_vec_h (v, 0);
247 }
248
249 /* Local variable naming macro (prevents collisions with other macro naming). */
250 #define _v(var) _vec_##var
251
252 /** \brief Resize a vector (general version).
253    Add N elements to end of given vector V, return pointer to start of vector.
254    Vector will have room for H header bytes and will have user's data aligned
255    at alignment A (rounded to next power of 2).
256
257     @param V pointer to a vector
258     @param N number of elements to add
259     @param H header size in bytes (may be zero)
260     @param A alignment (may be zero)
261     @param S numa_id (may be zero)
262     @return V (value-result macro parameter)
263 */
264
265 #define vec_resize_has(V,N,H,A,S)                               \
266 do {                                                            \
267   word _v(n) = (N);                                             \
268   word _v(l) = vec_len (V);                                     \
269   V = _vec_resize_numa ((V), _v(n),                           \
270                           (_v(l) + _v(n)) * sizeof ((V)[0]),    \
271                           (H), (A),(S));                        \
272 } while (0)
273
274 /** \brief Resize a vector (less general version).
275    Add N elements to end of given vector V, return pointer to start of vector.
276    Vector will have room for H header bytes and will have user's data aligned
277    at alignment A (rounded to next power of 2).
278
279     @param V pointer to a vector
280     @param N number of elements to add
281     @param H header size in bytes (may be zero)
282     @param A alignment (may be zero)
283     @return V (value-result macro parameter)
284 */
285 #define vec_resize_ha(V,N,H,A) vec_resize_has(V,N,H,A,VEC_NUMA_UNSPECIFIED)
286
287 /** \brief Resize a vector (no header, unspecified alignment)
288    Add N elements to end of given vector V, return pointer to start of vector.
289    Vector will have room for H header bytes and will have user's data aligned
290    at alignment A (rounded to next power of 2).
291
292     @param V pointer to a vector
293     @param N number of elements to add
294     @return V (value-result macro parameter)
295 */
296 #define vec_resize(V,N)     vec_resize_ha(V,N,0,0)
297
298 /** \brief Resize a vector (no header, alignment specified).
299    Add N elements to end of given vector V, return pointer to start of vector.
300    Vector will have room for H header bytes and will have user's data aligned
301    at alignment A (rounded to next power of 2).
302
303     @param V pointer to a vector
304     @param N number of elements to add
305     @param A alignment (may be zero)
306     @return V (value-result macro parameter)
307 */
308
309 #define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
310
311 /** \brief Allocate space for N more elements
312
313     @param V pointer to a vector
314     @param N number of elements to add
315     @param H header size in bytes (may be zero)
316     @param A alignment (may be zero)
317     @return V (value-result macro parameter)
318 */
319
320 #define vec_alloc_ha(V,N,H,A)                   \
321 do {                                            \
322     uword _v(l) = vec_len (V);                  \
323     vec_resize_ha (V, N, H, A);                 \
324     _vec_len (V) = _v(l);                       \
325 } while (0)
326
327 /** \brief Allocate space for N more elements
328     (no header, unspecified alignment)
329
330     @param V pointer to a vector
331     @param N number of elements to add
332     @return V (value-result macro parameter)
333 */
334 #define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
335
336 /** \brief Allocate space for N more elements (no header, given alignment)
337     @param V pointer to a vector
338     @param N number of elements to add
339     @param A alignment (may be zero)
340     @return V (value-result macro parameter)
341 */
342
343 #define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
344
345 /** \brief Create new vector of given type and length (general version).
346     @param T type of elements in new vector
347     @param N number of elements to add
348     @param H header size in bytes (may be zero)
349     @param A alignment (may be zero)
350     @return V new vector
351 */
352 #define vec_new_ha(T,N,H,A)                                             \
353 ({                                                                      \
354   word _v(n) = (N);                                                     \
355   (T *)_vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A));      \
356 })
357
358 /** \brief Create new vector of given type and length
359     (unspecified alignment, no header).
360
361     @param T type of elements in new vector
362     @param N number of elements to add
363     @return V new vector
364 */
365 #define vec_new(T,N)           vec_new_ha(T,N,0,0)
366 /** \brief Create new vector of given type and length
367     (alignment specified, no header).
368
369     @param T type of elements in new vector
370     @param N number of elements to add
371     @param A alignment (may be zero)
372     @return V new vector
373 */
374 #define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
375
376 /** \brief Free vector's memory (general version)
377
378     @param V pointer to a vector
379     @param H size of header in bytes
380     @return V (value-result parameter, V=0)
381 */
382 #define vec_free_h(V,H)                         \
383 do {                                            \
384   if (V)                                        \
385     {                                           \
386       clib_mem_free (vec_header ((V), (H)));    \
387       V = 0;                                    \
388     }                                           \
389 } while (0)
390
391 /** \brief Free vector's memory (no header).
392     @param V pointer to a vector
393     @return V (value-result parameter, V=0)
394 */
395 #define vec_free(V) vec_free_h(V,0)
396
397 void vec_free_not_inline (void *v);
398
399 /**\brief Free vector user header (syntactic sugar)
400    @param h vector header
401    @void
402 */
403 #define vec_free_header(h) clib_mem_free (h)
404
405 /** \brief Return copy of vector (general version).
406
407     @param V pointer to a vector
408     @param H size of header in bytes
409     @param A alignment (may be zero)
410     @param S numa (may be VEC_NUMA_UNSPECIFIED)
411
412     @return Vdup copy of vector
413 */
414
415 #define vec_dup_ha_numa(V,H,A,S)                      \
416 ({                                                      \
417   __typeof__ ((V)[0]) * _v(v) = 0;                      \
418   uword _v(l) = vec_len (V);                            \
419   if (_v(l) > 0)                                        \
420     {                                                   \
421       vec_resize_has (_v(v), _v(l), (H), (A), (S));     \
422       clib_memcpy_fast (_v(v), (V), _v(l) * sizeof ((V)[0]));\
423     }                                                   \
424   _v(v);                                                \
425 })
426
427 /** \brief Return copy of vector (VEC_NUMA_UNSPECIFIED).
428
429     @param V pointer to a vector
430     @param H size of header in bytes
431     @param A alignment (may be zero)
432
433     @return Vdup copy of vector
434 */
435 #define vec_dup_ha(V,H,A) \
436   vec_dup_ha_numa(V,H,A,VEC_NUMA_UNSPECIFIED)
437
438
439 /** \brief Return copy of vector (no header, no alignment)
440
441     @param V pointer to a vector
442     @return Vdup copy of vector
443 */
444 #define vec_dup(V) vec_dup_ha(V,0,0)
445
446 /** \brief Return copy of vector (no header, alignment specified).
447
448     @param V pointer to a vector
449     @param A alignment (may be zero)
450
451     @return Vdup copy of vector
452 */
453 #define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
454
455 /** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
456     sizeof(DST[0])
457
458     @param DST destination
459     @param SRC source
460 */
461 #define vec_copy(DST,SRC) clib_memcpy_fast (DST, SRC, vec_len (DST) * \
462                                        sizeof ((DST)[0]))
463
464 /** \brief Clone a vector. Make a new vector with the
465     same size as a given vector but possibly with a different type.
466
467     @param NEW_V pointer to new vector
468     @param OLD_V pointer to old vector
469 */
470 #define vec_clone(NEW_V,OLD_V)                                                  \
471 do {                                                                            \
472   (NEW_V) = 0;                                                                  \
473   (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V),                              \
474                          vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0));      \
475 } while (0)
476
477 /** \brief Make sure vector is long enough for given index (general version).
478
479     @param V (possibly NULL) pointer to a vector.
480     @param I vector index which will be valid upon return
481     @param H header size in bytes (may be zero)
482     @param A alignment (may be zero)
483     @param N numa_id (may be zero)
484     @return V (value-result macro parameter)
485 */
486
487 #define vec_validate_han(V,I,H,A,N)                                     \
488 do {                                                                    \
489   void *oldheap;                                                        \
490   STATIC_ASSERT(A==0 || ((A % sizeof(V[0]))==0)                         \
491         || ((sizeof(V[0]) % A) == 0),                                   \
492     "vector validate aligned on incorrectly sized object");             \
493   word _v(i) = (I);                                                     \
494   word _v(l) = vec_len (V);                                             \
495   if (_v(i) >= _v(l))                                                   \
496     {                                                                   \
497       /* switch to the per-numa heap if directed */                   \
498       if (PREDICT_FALSE(N != VEC_NUMA_UNSPECIFIED))                   \
499         {                                                               \
500            oldheap = clib_mem_get_per_cpu_heap();                       \
501            clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap(N)); \
502         }                                                               \
503                                                                         \
504       vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A));               \
505       /* Must zero new space since user may have previously             \
506          used e.g. _vec_len (v) -= 10 */                                \
507       clib_memset ((V) + _v(l), 0,                                      \
508                    (1 + (_v(i) - _v(l))) * sizeof ((V)[0]));            \
509       /* Switch back to the global heap */                              \
510       if (PREDICT_FALSE (N != VEC_NUMA_UNSPECIFIED))                  \
511         clib_mem_set_per_cpu_heap (oldheap);                            \
512     }                                                                   \
513 } while (0)
514
515 #define vec_validate_ha(V,I,H,A) vec_validate_han(V,I,H,A,VEC_NUMA_UNSPECIFIED)
516
517 /** \brief Make sure vector is long enough for given index
518     (no header, unspecified alignment)
519
520     @param V (possibly NULL) pointer to a vector.
521     @param I vector index which will be valid upon return
522     @return V (value-result macro parameter)
523 */
524 #define vec_validate(V,I)           vec_validate_ha(V,I,0,0)
525
526 /** \brief Make sure vector is long enough for given index
527     (no header, specified alignment)
528
529     @param V (possibly NULL) pointer to a vector.
530     @param I vector index which will be valid upon return
531     @param A alignment (may be zero)
532     @return V (value-result macro parameter)
533 */
534
535 #define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
536
537 /** \brief Make sure vector is long enough for given index
538     and initialize empty space (general version)
539
540     @param V (possibly NULL) pointer to a vector.
541     @param I vector index which will be valid upon return
542     @param INIT initial value (can be a complex expression!)
543     @param H header size in bytes (may be zero)
544     @param A alignment (may be zero)
545     @return V (value-result macro parameter)
546 */
547 #define vec_validate_init_empty_ha(V,I,INIT,H,A)                \
548 do {                                                            \
549   word _v(i) = (I);                                             \
550   word _v(l) = vec_len (V);                                     \
551   if (_v(i) >= _v(l))                                           \
552     {                                                           \
553       vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A));       \
554       while (_v(l) <= _v(i))                                    \
555         {                                                       \
556           (V)[_v(l)] = (INIT);                                  \
557           _v(l)++;                                              \
558         }                                                       \
559     }                                                           \
560 } while (0)
561
562 /** \brief Make sure vector is long enough for given index
563     and initialize empty space (no header, unspecified alignment)
564
565     @param V (possibly NULL) pointer to a vector.
566     @param I vector index which will be valid upon return
567     @param INIT initial value (can be a complex expression!)
568     @return V (value-result macro parameter)
569 */
570
571 #define vec_validate_init_empty(V,I,INIT) \
572   vec_validate_init_empty_ha(V,I,INIT,0,0)
573
574 /** \brief Make sure vector is long enough for given index
575     and initialize empty space (no header, alignment alignment)
576
577     @param V (possibly NULL) pointer to a vector.
578     @param I vector index which will be valid upon return
579     @param INIT initial value (can be a complex expression!)
580     @param A alignment (may be zero)
581     @return V (value-result macro parameter)
582 */
583 #define vec_validate_init_empty_aligned(V,I,INIT,A) \
584   vec_validate_init_empty_ha(V,I,INIT,0,A)
585
586 /** \brief Add 1 element to end of vector (general version).
587
588     @param V pointer to a vector
589     @param E element to add
590     @param H header size in bytes (may be zero)
591     @param A alignment (may be zero)
592     @return V (value-result macro parameter)
593 */
594 #define vec_add1_ha(V,E,H,A)                                            \
595 do {                                                                    \
596   word _v(l) = vec_len (V);                                             \
597   V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A));    \
598   (V)[_v(l)] = (E);                                                     \
599 } while (0)
600
601 /** \brief Add 1 element to end of vector (unspecified alignment).
602
603     @param V pointer to a vector
604     @param E element to add
605     @return V (value-result macro parameter)
606 */
607 #define vec_add1(V,E)           vec_add1_ha(V,E,0,0)
608
609 /** \brief Add 1 element to end of vector (alignment specified).
610
611     @param V pointer to a vector
612     @param E element to add
613     @param A alignment (may be zero)
614     @return V (value-result macro parameter)
615 */
616 #define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
617
618 /** \brief Add N elements to end of vector V,
619     return pointer to new elements in P. (general version)
620
621     @param V pointer to a vector
622     @param P pointer to new vector element(s)
623     @param N number of elements to add
624     @param H header size in bytes (may be zero)
625     @param A alignment (may be zero)
626     @return V and P (value-result macro parameters)
627 */
628 #define vec_add2_ha(V,P,N,H,A)                                                  \
629 do {                                                                            \
630   word _v(n) = (N);                                                             \
631   word _v(l) = vec_len (V);                                                     \
632   V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A));    \
633   P = (V) + _v(l);                                                              \
634 } while (0)
635
636 /** \brief Add N elements to end of vector V,
637     return pointer to new elements in P. (no header, unspecified alignment)
638
639     @param V pointer to a vector
640     @param P pointer to new vector element(s)
641     @param N number of elements to add
642     @return V and P (value-result macro parameters)
643 */
644
645 #define vec_add2(V,P,N)           vec_add2_ha(V,P,N,0,0)
646
647 /** \brief Add N elements to end of vector V,
648     return pointer to new elements in P. (no header, alignment specified)
649
650     @param V pointer to a vector
651     @param P pointer to new vector element(s)
652     @param N number of elements to add
653     @param A alignment (may be zero)
654     @return V and P (value-result macro parameters)
655 */
656
657 #define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
658
659 /** \brief Add N elements to end of vector V (general version)
660
661     @param V pointer to a vector
662     @param E pointer to element(s) to add
663     @param N number of elements to add
664     @param H header size in bytes (may be zero)
665     @param A alignment (may be zero)
666     @return V (value-result macro parameter)
667 */
668 #define vec_add_ha(V,E,N,H,A)                                                   \
669 do {                                                                            \
670   word _v(n) = (N);                                                             \
671   word _v(l) = vec_len (V);                                                     \
672   V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A));    \
673   clib_memcpy_fast ((V) + _v(l), (E), _v(n) * sizeof ((V)[0]));                 \
674 } while (0)
675
676 /** \brief Add N elements to end of vector V (no header, unspecified alignment)
677
678     @param V pointer to a vector
679     @param E pointer to element(s) to add
680     @param N number of elements to add
681     @return V (value-result macro parameter)
682 */
683 #define vec_add(V,E,N)           vec_add_ha(V,E,N,0,0)
684
685 /** \brief Add N elements to end of vector V (no header, specified alignment)
686
687     @param V pointer to a vector
688     @param E pointer to element(s) to add
689     @param N number of elements to add
690     @param A alignment (may be zero)
691     @return V (value-result macro parameter)
692 */
693 #define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
694
695 /** \brief Returns last element of a vector and decrements its length
696
697     @param V pointer to a vector
698     @return E element removed from the end of the vector
699 */
700 #define vec_pop(V)                              \
701 ({                                              \
702   uword _v(l) = vec_len (V);                    \
703   ASSERT (_v(l) > 0);                           \
704   _v(l) -= 1;                                   \
705   _vec_len (V) = _v (l);                        \
706   (V)[_v(l)];                                   \
707 })
708
709 /** \brief Set E to the last element of a vector, decrement vector length
710     @param V pointer to a vector
711     @param E pointer to the last vector element
712     @return E element removed from the end of the vector
713     (value-result macro parameter
714 */
715
716 #define vec_pop2(V,E)                           \
717 ({                                              \
718   uword _v(l) = vec_len (V);                    \
719   if (_v(l) > 0) (E) = vec_pop (V);             \
720   _v(l) > 0;                                    \
721 })
722
723 /** \brief Insert N vector elements starting at element M,
724     initialize new elements (general version).
725
726     @param V (possibly NULL) pointer to a vector.
727     @param N number of elements to insert
728     @param M insertion point
729     @param INIT initial value (can be a complex expression!)
730     @param H header size in bytes (may be zero)
731     @param A alignment (may be zero)
732     @return V (value-result macro parameter)
733 */
734 #define vec_insert_init_empty_ha(V,N,M,INIT,H,A)        \
735 do {                                                    \
736   word _v(l) = vec_len (V);                             \
737   word _v(n) = (N);                                     \
738   word _v(m) = (M);                                     \
739   V = _vec_resize ((V),                                 \
740                    _v(n),                               \
741                    (_v(l) + _v(n))*sizeof((V)[0]),      \
742                    (H), (A));                           \
743   ASSERT (_v(m) <= _v(l));                              \
744   memmove ((V) + _v(m) + _v(n),                         \
745            (V) + _v(m),                                 \
746            (_v(l) - _v(m)) * sizeof ((V)[0]));          \
747   clib_memset  ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0]));    \
748 } while (0)
749
750 /** \brief Insert N vector elements starting at element M,
751     initialize new elements to zero (general version)
752
753     @param V (possibly NULL) pointer to a vector.
754     @param N number of elements to insert
755     @param M insertion point
756     @param H header size in bytes (may be zero)
757     @param A alignment (may be zero)
758     @return V (value-result macro parameter)
759 */
760 #define vec_insert_ha(V,N,M,H,A)    vec_insert_init_empty_ha(V,N,M,0,H,A)
761
762 /** \brief Insert N vector elements starting at element M,
763     initialize new elements to zero (no header, unspecified alignment)
764
765     @param V (possibly NULL) pointer to a vector.
766     @param N number of elements to insert
767     @param M insertion point
768     @return V (value-result macro parameter)
769 */
770 #define vec_insert(V,N,M)           vec_insert_ha(V,N,M,0,0)
771
772 /** \brief Insert N vector elements starting at element M,
773     initialize new elements to zero (no header, alignment specified)
774
775     @param V (possibly NULL) pointer to a vector.
776     @param N number of elements to insert
777     @param M insertion point
778     @param A alignment (may be zero)
779     @return V (value-result macro parameter)
780 */
781 #define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
782
783 /** \brief Insert N vector elements starting at element M,
784     initialize new elements (no header, unspecified alignment)
785
786     @param V (possibly NULL) pointer to a vector.
787     @param N number of elements to insert
788     @param M insertion point
789     @param INIT initial value (can be a complex expression!)
790     @return V (value-result macro parameter)
791 */
792
793 #define vec_insert_init_empty(V,N,M,INIT) \
794   vec_insert_init_empty_ha(V,N,M,INIT,0,0)
795 /* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
796
797 /** \brief Insert N vector elements starting at element M,
798     initialize new elements (no header, specified alignment)
799
800     @param V (possibly NULL) pointer to a vector.
801     @param N number of elements to insert
802     @param M insertion point
803     @param INIT initial value (can be a complex expression!)
804     @param A alignment (may be zero)
805     @return V (value-result macro parameter)
806 */
807 #define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
808   vec_insert_init_empty_ha(V,N,M,INIT,0,A)
809
810 /** \brief Insert N vector elements starting at element M,
811     insert given elements (general version)
812
813     @param V (possibly NULL) pointer to a vector.
814     @param E element(s) to insert
815     @param N number of elements to insert
816     @param M insertion point
817     @param H header size in bytes (may be zero)
818     @param A alignment (may be zero)
819     @return V (value-result macro parameter)
820 */
821
822 #define vec_insert_elts_ha(V,E,N,M,H,A)                 \
823 do {                                                    \
824   word _v(l) = vec_len (V);                             \
825   word _v(n) = (N);                                     \
826   word _v(m) = (M);                                     \
827   V = _vec_resize ((V),                                 \
828                    _v(n),                               \
829                    (_v(l) + _v(n))*sizeof((V)[0]),      \
830                    (H), (A));                           \
831   ASSERT (_v(m) <= _v(l));                              \
832   memmove ((V) + _v(m) + _v(n),                         \
833            (V) + _v(m),                                 \
834            (_v(l) - _v(m)) * sizeof ((V)[0]));          \
835   clib_memcpy_fast ((V) + _v(m), (E),                   \
836                _v(n) * sizeof ((V)[0]));                \
837 } while (0)
838
839 /** \brief Insert N vector elements starting at element M,
840     insert given elements (no header, unspecified alignment)
841
842     @param V (possibly NULL) pointer to a vector.
843     @param E element(s) to insert
844     @param N number of elements to insert
845     @param M insertion point
846     @return V (value-result macro parameter)
847 */
848 #define vec_insert_elts(V,E,N,M)           vec_insert_elts_ha(V,E,N,M,0,0)
849
850 /** \brief Insert N vector elements starting at element M,
851     insert given elements (no header, specified alignment)
852
853     @param V (possibly NULL) pointer to a vector.
854     @param E element(s) to insert
855     @param N number of elements to insert
856     @param M insertion point
857     @param A alignment (may be zero)
858     @return V (value-result macro parameter)
859 */
860 #define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
861
862 /** \brief Delete N elements starting at element M
863
864     @param V pointer to a vector
865     @param N number of elements to delete
866     @param M first element to delete
867     @return V (value-result macro parameter)
868 */
869 #define vec_delete(V,N,M)                                       \
870 do {                                                            \
871   word _v(l) = vec_len (V);                                     \
872   word _v(n) = (N);                                             \
873   word _v(m) = (M);                                             \
874   /* Copy over deleted elements. */                             \
875   if (_v(l) - _v(n) - _v(m) > 0)                                \
876     memmove ((V) + _v(m), (V) + _v(m) + _v(n),                  \
877              (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0]));        \
878   /* Zero empty space at end (for future re-allocation). */     \
879   if (_v(n) > 0)                                                \
880     clib_memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0]));      \
881   _vec_len (V) -= _v(n);                                        \
882   CLIB_MEM_POISON(vec_end(V), _v(n) * sizeof ((V)[0]));         \
883 } while (0)
884
885 /** \brief Delete the element at index I
886
887     @param V pointer to a vector
888     @param I index to delete
889 */
890 #define vec_del1(v,i)                           \
891 do {                                            \
892   uword _vec_del_l = _vec_len (v) - 1;          \
893   uword _vec_del_i = (i);                       \
894   if (_vec_del_i < _vec_del_l)                  \
895     (v)[_vec_del_i] = (v)[_vec_del_l];          \
896   _vec_len (v) = _vec_del_l;                    \
897   CLIB_MEM_POISON(vec_end(v), sizeof ((v)[0])); \
898 } while (0)
899
900 /** \brief Append v2 after v1. Result in v1.
901     @param V1 target vector
902     @param V2 vector to append
903 */
904
905 #define vec_append(v1,v2)                                               \
906 do {                                                                    \
907   uword _v(l1) = vec_len (v1);                                          \
908   uword _v(l2) = vec_len (v2);                                          \
909                                                                         \
910   v1 = _vec_resize ((v1), _v(l2),                                       \
911                     (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0);        \
912   clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0]));            \
913 } while (0)
914
915 /** \brief Append v2 after v1. Result in v1. Specified alignment.
916     @param V1 target vector
917     @param V2 vector to append
918     @param align required alignment
919 */
920
921 #define vec_append_aligned(v1,v2,align)                                 \
922 do {                                                                    \
923   uword _v(l1) = vec_len (v1);                                          \
924   uword _v(l2) = vec_len (v2);                                          \
925                                                                         \
926   v1 = _vec_resize ((v1), _v(l2),                                       \
927                     (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align);    \
928   clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0]));            \
929 } while (0)
930
931 /** \brief Prepend v2 before v1. Result in v1.
932     @param V1 target vector
933     @param V2 vector to prepend
934 */
935
936 #define vec_prepend(v1,v2)                                              \
937 do {                                                                    \
938   uword _v(l1) = vec_len (v1);                                          \
939   uword _v(l2) = vec_len (v2);                                          \
940                                                                         \
941   v1 = _vec_resize ((v1), _v(l2),                                       \
942                     (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0);        \
943   memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0]));             \
944   clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0]));                  \
945 } while (0)
946
947 /** \brief Prepend v2 before v1. Result in v1. Specified alignment
948     @param V1 target vector
949     @param V2 vector to prepend
950     @param align required alignment
951 */
952
953 #define vec_prepend_aligned(v1,v2,align)                                \
954 do {                                                                    \
955   uword _v(l1) = vec_len (v1);                                          \
956   uword _v(l2) = vec_len (v2);                                          \
957                                                                         \
958   v1 = _vec_resize ((v1), _v(l2),                                       \
959                     (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align);    \
960   memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0]));             \
961   clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0]));                  \
962 } while (0)
963
964
965 /** \brief Zero all vector elements. Null-pointer tolerant.
966     @param var Vector to zero
967 */
968 #define vec_zero(var)                                           \
969 do {                                                            \
970   if (var)                                                      \
971     clib_memset ((var), 0, vec_len (var) * sizeof ((var)[0]));  \
972 } while (0)
973
974 /** \brief Set all vector elements to given value. Null-pointer tolerant.
975     @param v vector to set
976     @param val value for each vector element
977 */
978 #define vec_set(v,val)                          \
979 do {                                            \
980   word _v(i);                                   \
981   __typeof__ ((v)[0]) _val = (val);             \
982   for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
983     (v)[_v(i)] = _val;                          \
984 } while (0)
985
986 #ifdef CLIB_UNIX
987 #include <stdlib.h>             /* for qsort */
988 #endif
989
990 /** \brief Compare two vectors, not NULL-pointer tolerant
991
992     @param v1 Pointer to a vector
993     @param v2 Pointer to a vector
994     @return 1 if equal, 0 if unequal
995 */
996 #define vec_is_equal(v1,v2) \
997   (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
998
999 /** \brief Compare two vectors (only applicable to vectors of signed numbers).
1000    Used in qsort compare functions.
1001
1002     @param v1 Pointer to a vector
1003     @param v2 Pointer to a vector
1004     @return -1, 0, +1
1005 */
1006 #define vec_cmp(v1,v2)                                  \
1007 ({                                                      \
1008   word _v(i), _v(cmp), _v(l);                           \
1009   _v(l) = clib_min (vec_len (v1), vec_len (v2));        \
1010   _v(cmp) = 0;                                          \
1011   for (_v(i) = 0; _v(i) < _v(l); _v(i)++) {             \
1012     _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)];                \
1013     if (_v(cmp))                                        \
1014       break;                                            \
1015   }                                                     \
1016   if (_v(cmp) == 0 && _v(l) > 0)                        \
1017     _v(cmp) = vec_len(v1) - vec_len(v2);                \
1018   (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0));          \
1019 })
1020
1021 /** \brief Search a vector for the index of the entry that matches.
1022
1023     @param v Pointer to a vector
1024     @param E Entry to match
1025     @return index of match or ~0
1026 */
1027 #define vec_search(v,E)                                 \
1028 ({                                                      \
1029   word _v(i) = 0;                                       \
1030   while (_v(i) < vec_len(v))                            \
1031   {                                                     \
1032     if ((v)[_v(i)] == E)                                        \
1033       break;                                            \
1034     _v(i)++;                                            \
1035   }                                                     \
1036   if (_v(i) == vec_len(v))                              \
1037     _v(i) = ~0;                                         \
1038   _v(i);                                                \
1039 })
1040
1041 /** \brief Search a vector for the index of the entry that matches.
1042
1043     @param v Pointer to a vector
1044     @param E Pointer to entry to match
1045     @param fn Comparison function !0 => match
1046     @return index of match or ~0
1047 */
1048 #define vec_search_with_function(v,E,fn)                \
1049 ({                                                      \
1050   word _v(i) = 0;                                       \
1051   while (_v(i) < vec_len(v))                            \
1052   {                                                     \
1053     if (0 != fn(&(v)[_v(i)], (E)))                      \
1054       break;                                            \
1055     _v(i)++;                                            \
1056   }                                                     \
1057   if (_v(i) == vec_len(v))                              \
1058     _v(i) = ~0;                                         \
1059   _v(i);                                                \
1060 })
1061
1062 /** \brief Sort a vector using the supplied element comparison function
1063
1064     Does not depend on the underlying implementation to deal correctly
1065     with null, zero-long, or 1-long vectors
1066
1067     @param vec vector to sort
1068     @param f comparison function
1069 */
1070 #define vec_sort_with_function(vec,f)                           \
1071 do {                                                            \
1072   if (vec_len (vec) > 1)                                        \
1073     qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f));  \
1074 } while (0)
1075
1076 /** \brief Make a vector containing a NULL terminated c-string.
1077
1078     @param V (possibly NULL) pointer to a vector.
1079     @param S pointer to string buffer.
1080     @param L string length (NOT including the terminating NULL; a la strlen())
1081 */
1082 #define vec_validate_init_c_string(V, S, L)     \
1083   do {                                          \
1084     vec_reset_length (V);                       \
1085     vec_validate ((V), (L));                    \
1086     if ((S) && (L))                             \
1087         clib_memcpy_fast ((V), (S), (L));            \
1088     (V)[(L)] = 0;                               \
1089   } while (0)
1090
1091
1092 /** \brief Test whether a vector is a NULL terminated c-string.
1093
1094     @param V (possibly NULL) pointer to a vector.
1095     @return BOOLEAN indicating if the vector c-string is null terminated.
1096 */
1097 #define vec_c_string_is_terminated(V)                   \
1098   (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
1099
1100 /** \brief (If necessary) NULL terminate a vector containing a c-string.
1101
1102     @param V (possibly NULL) pointer to a vector.
1103     @return V (value-result macro parameter)
1104 */
1105 #define vec_terminate_c_string(V)               \
1106   do {                                          \
1107     u32 vl = vec_len ((V));                     \
1108     if (!vec_c_string_is_terminated(V))         \
1109       {                                         \
1110         vec_validate ((V), vl);                 \
1111         (V)[vl] = 0;                            \
1112       }                                         \
1113   } while (0)
1114
1115 #endif /* included_vec_h */
1116
1117
1118 /*
1119  * fd.io coding-style-patch-verification: ON
1120  *
1121  * Local Variables:
1122  * eval: (c-set-style "gnu")
1123  * End:
1124  */