blob: 3f50bd2562590c3aafcdf2b558e4deead38a707c [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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
Dave Barachc3799992016-08-15 11:12:27 -040041#include <vppinfra/clib.h> /* word, etc */
42#include <vppinfra/mem.h> /* clib_mem_free */
Ed Warnickecb9cada2015-12-08 15:45:58 -070043#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
Dave Barach2bc1eba2016-01-19 15:10:27 -050062 The user pointer contains the address of vector element # 0. Null
Dave Barachc3799992016-08-15 11:12:27 -040063 pointer vectors are valid and mean a zero length vector.
Dave Barach2bc1eba2016-01-19 15:10:27 -050064
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.
Ed Warnickecb9cada2015-12-08 15:45:58 -070069
70 Typically, the header is not present. Headers allow for other
71 data structures to be built atop CLIB vectors.
72
Dave Wallace4659d0e2018-12-13 12:29:44 -050073 Users may specify the alignment for first data element of a vector
74 via the vec_*_aligned macros.
Ed Warnickecb9cada2015-12-08 15:45:58 -070075
Dave Wallace4659d0e2018-12-13 12:29:44 -050076 Vector elements can be any C type e.g. (int, double, struct bar).
Ed Warnickecb9cada2015-12-08 15:45:58 -070077 This is also true for data types built atop vectors (e.g. heap,
78 pool, etc.).
79
Dave Wallace4659d0e2018-12-13 12:29:44 -050080 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.
Ed Warnickecb9cada2015-12-08 15:45:58 -070085
Dave Barachc3799992016-08-15 11:12:27 -040086 Standard programming error: memorize a pointer to the ith element
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 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
Dave Barachc3799992016-08-15 11:12:27 -040089 which are invariant.
Ed Warnickecb9cada2015-12-08 15:45:58 -070090 */
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)
Dave Baracha690fdb2020-01-21 12:34:55 -050099 @param numa_id numa id (may be zero)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100 @return v_prime pointer to resized vector, may or may not equal v
101*/
Dave Barachc3799992016-08-15 11:12:27 -0400102void *vec_resize_allocate_memory (void *v,
103 word length_increment,
104 uword data_bytes,
Dave Baracha690fdb2020-01-21 12:34:55 -0500105 uword header_bytes, uword data_align,
106 uword numa_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700107
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)
Dave Baracha690fdb2020-01-21 12:34:55 -0500115 @param numa_id (may be ~0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116 @return v_prime pointer to resized vector, may or may not equal v
117*/
118
Andreas Schultzc458c492020-03-26 14:18:52 +0000119#define _vec_resize_numa(V,L,DB,HB,A,S) \
120({ \
121 __typeof__ ((V)) _V; \
BenoƮt Ganned25147d2020-06-30 18:17:06 +0200122 _V = _vec_resize_inline((void *)V,L,DB,HB,clib_max((__alignof__((V)[0])),(A)),(S)); \
Andreas Schultzc458c492020-03-26 14:18:52 +0000123 _V; \
124})
Dave Baracha690fdb2020-01-21 12:34:55 -0500125
126#define _vec_resize(V,L,DB,HB,A) \
127 _vec_resize_numa(V,L,DB,HB,A,VEC_NUMA_UNSPECIFIED)
Damjan Marion2f25ef32018-05-04 20:45:41 +0200128
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129always_inline void *
Damjan Marion2f25ef32018-05-04 20:45:41 +0200130_vec_resize_inline (void *v,
131 word length_increment,
Dave Baracha690fdb2020-01-21 12:34:55 -0500132 uword data_bytes, uword header_bytes, uword data_align,
133 uword numa_id)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700134{
Dave Barachc3799992016-08-15 11:12:27 -0400135 vec_header_t *vh = _vec_find (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700136 uword new_data_bytes, aligned_header_bytes;
Dave Baracha690fdb2020-01-21 12:34:55 -0500137 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700138
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 {
Dave Barachc3799992016-08-15 11:12:27 -0400145 void *p = v - aligned_header_bytes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146
Dave Baracha690fdb2020-01-21 12:34:55 -0500147 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
Ed Warnickecb9cada2015-12-08 15:45:58 -0700153 /* 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 {
BenoƮt Ganne9fb6d402019-04-15 15:28:21 +0200159 CLIB_MEM_UNPOISON (v, data_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700160 vh->len += length_increment;
Dave Baracha690fdb2020-01-21 12:34:55 -0500161 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
162 clib_mem_set_per_cpu_heap (oldheap);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163 return v;
164 }
Dave Baracha690fdb2020-01-21 12:34:55 -0500165 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
166 clib_mem_set_per_cpu_heap (oldheap);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700167 }
168
169 /* Slow path: call helper function. */
Dave Barachc3799992016-08-15 11:12:27 -0400170 return vec_resize_allocate_memory (v, length_increment, data_bytes,
171 header_bytes,
172 clib_max (sizeof (vec_header_t),
Dave Baracha690fdb2020-01-21 12:34:55 -0500173 data_align), numa_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174}
175
Florin Corasef5d5aa2017-11-02 19:28:09 -0400176/** \brief Determine if vector will resize with next allocation
Dave Barach614ac5d2017-02-06 09:28:03 -0500177
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)
Florin Corasef5d5aa2017-11-02 19:28:09 -0400183 @return 1 if vector will resize 0 otherwise
Dave Barach614ac5d2017-02-06 09:28:03 -0500184*/
185
186always_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{
Dave Barach614ac5d2017-02-06 09:28:03 -0500192 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))
Florin Corasef5d5aa2017-11-02 19:28:09 -0400207 return 0;
Dave Barach614ac5d2017-02-06 09:28:03 -0500208 }
209 return 1;
210}
211
Miklos Tirpake700df82021-01-13 10:00:38 +0100212/** \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
Dave Barachc3799992016-08-15 11:12:27 -0400227/** \brief Predicate function, says whether the supplied vector is a clib heap
228 object (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229
230 @param v pointer to a vector
231 @param header_bytes vector header size in bytes (may be zero)
232 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400233*/
234uword clib_mem_is_vec_h (void *v, uword header_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235
236
Dave Barachc3799992016-08-15 11:12:27 -0400237/** \brief Predicate function, says whether the supplied vector is a clib heap
Ed Warnickecb9cada2015-12-08 15:45:58 -0700238 object
239
240 @param v pointer to a vector
241 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400242*/
243always_inline uword
244clib_mem_is_vec (void *v)
245{
246 return clib_mem_is_vec_h (v, 0);
247}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248
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)
Dave Baracha690fdb2020-01-21 12:34:55 -0500261 @param S numa_id (may be zero)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700262 @return V (value-result macro parameter)
263*/
264
Dave Baracha690fdb2020-01-21 12:34:55 -0500265#define vec_resize_has(V,N,H,A,S) \
266do { \
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)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700272} while (0)
273
Dave Baracha690fdb2020-01-21 12:34:55 -0500274/** \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
Ed Warnickecb9cada2015-12-08 15:45:58 -0700287/** \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
Dave Barachc3799992016-08-15 11:12:27 -0400311/** \brief Allocate space for N more elements
Ed Warnickecb9cada2015-12-08 15:45:58 -0700312
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) \
321do { \
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
Dave Barachc3799992016-08-15 11:12:27 -0400327/** \brief Allocate space for N more elements
328 (no header, unspecified alignment)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700329
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*/
Andreas Schultzc458c492020-03-26 14:18:52 +0000352#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)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700356})
357
Dave Barachc3799992016-08-15 11:12:27 -0400358/** \brief Create new vector of given type and length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700359 (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)
Dave Barachc3799992016-08-15 11:12:27 -0400366/** \brief Create new vector of given type and length
367 (alignment specified, no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700368
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
Damjan Marion05563c92022-03-17 18:29:32 +0100376/** \brief Free vector's memory (no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377 @param V pointer to a vector
Ed Warnickecb9cada2015-12-08 15:45:58 -0700378 @return V (value-result parameter, V=0)
379*/
Damjan Marion05563c92022-03-17 18:29:32 +0100380#define vec_free(V) \
Damjan Mariona4a28f02022-03-17 15:46:25 +0100381 do \
382 { \
383 if (V) \
384 { \
385 clib_mem_free (vec_header ((V))); \
386 V = 0; \
387 } \
388 } \
389 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390
Dave Barache09ae012020-08-19 06:59:53 -0400391void vec_free_not_inline (void *v);
392
Ed Warnickecb9cada2015-12-08 15:45:58 -0700393/**\brief Free vector user header (syntactic sugar)
394 @param h vector header
395 @void
396*/
397#define vec_free_header(h) clib_mem_free (h)
398
399/** \brief Return copy of vector (general version).
400
401 @param V pointer to a vector
402 @param H size of header in bytes
403 @param A alignment (may be zero)
Dave Baracha690fdb2020-01-21 12:34:55 -0500404 @param S numa (may be VEC_NUMA_UNSPECIFIED)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405
406 @return Vdup copy of vector
407*/
408
Dave Baracha690fdb2020-01-21 12:34:55 -0500409#define vec_dup_ha_numa(V,H,A,S) \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700410({ \
411 __typeof__ ((V)[0]) * _v(v) = 0; \
412 uword _v(l) = vec_len (V); \
413 if (_v(l) > 0) \
414 { \
Dave Baracha690fdb2020-01-21 12:34:55 -0500415 vec_resize_has (_v(v), _v(l), (H), (A), (S)); \
Dave Barach178cf492018-11-13 16:34:13 -0500416 clib_memcpy_fast (_v(v), (V), _v(l) * sizeof ((V)[0]));\
Ed Warnickecb9cada2015-12-08 15:45:58 -0700417 } \
418 _v(v); \
419})
420
Dave Baracha690fdb2020-01-21 12:34:55 -0500421/** \brief Return copy of vector (VEC_NUMA_UNSPECIFIED).
422
423 @param V pointer to a vector
424 @param H size of header in bytes
425 @param A alignment (may be zero)
426
427 @return Vdup copy of vector
428*/
429#define vec_dup_ha(V,H,A) \
430 vec_dup_ha_numa(V,H,A,VEC_NUMA_UNSPECIFIED)
431
432
Ed Warnickecb9cada2015-12-08 15:45:58 -0700433/** \brief Return copy of vector (no header, no alignment)
434
435 @param V pointer to a vector
436 @return Vdup copy of vector
437*/
438#define vec_dup(V) vec_dup_ha(V,0,0)
439
440/** \brief Return copy of vector (no header, alignment specified).
441
442 @param V pointer to a vector
443 @param A alignment (may be zero)
444
445 @return Vdup copy of vector
446*/
447#define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
448
449/** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
450 sizeof(DST[0])
451
Dave Barachc3799992016-08-15 11:12:27 -0400452 @param DST destination
Ed Warnickecb9cada2015-12-08 15:45:58 -0700453 @param SRC source
454*/
Dave Barach178cf492018-11-13 16:34:13 -0500455#define vec_copy(DST,SRC) clib_memcpy_fast (DST, SRC, vec_len (DST) * \
Damjan Marionf1213b82016-03-13 02:22:06 +0100456 sizeof ((DST)[0]))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700457
Dave Barachc3799992016-08-15 11:12:27 -0400458/** \brief Clone a vector. Make a new vector with the
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459 same size as a given vector but possibly with a different type.
460
461 @param NEW_V pointer to new vector
462 @param OLD_V pointer to old vector
463*/
464#define vec_clone(NEW_V,OLD_V) \
465do { \
466 (NEW_V) = 0; \
467 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
468 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
469} while (0)
470
471/** \brief Make sure vector is long enough for given index (general version).
472
Dave Barachc3799992016-08-15 11:12:27 -0400473 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700474 @param I vector index which will be valid upon return
475 @param H header size in bytes (may be zero)
476 @param A alignment (may be zero)
Dave Baracha690fdb2020-01-21 12:34:55 -0500477 @param N numa_id (may be zero)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700478 @return V (value-result macro parameter)
479*/
480
Dave Baracha690fdb2020-01-21 12:34:55 -0500481#define vec_validate_han(V,I,H,A,N) \
482do { \
483 void *oldheap; \
484 STATIC_ASSERT(A==0 || ((A % sizeof(V[0]))==0) \
485 || ((sizeof(V[0]) % A) == 0), \
486 "vector validate aligned on incorrectly sized object"); \
487 word _v(i) = (I); \
488 word _v(l) = vec_len (V); \
489 if (_v(i) >= _v(l)) \
490 { \
491 /* switch to the per-numa heap if directed */ \
492 if (PREDICT_FALSE(N != VEC_NUMA_UNSPECIFIED)) \
493 { \
494 oldheap = clib_mem_get_per_cpu_heap(); \
495 clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap(N)); \
496 } \
497 \
498 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
499 /* Must zero new space since user may have previously \
500 used e.g. _vec_len (v) -= 10 */ \
501 clib_memset ((V) + _v(l), 0, \
502 (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
503 /* Switch back to the global heap */ \
504 if (PREDICT_FALSE (N != VEC_NUMA_UNSPECIFIED)) \
505 clib_mem_set_per_cpu_heap (oldheap); \
506 } \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700507} while (0)
508
Dave Baracha690fdb2020-01-21 12:34:55 -0500509#define vec_validate_ha(V,I,H,A) vec_validate_han(V,I,H,A,VEC_NUMA_UNSPECIFIED)
510
Dave Barachc3799992016-08-15 11:12:27 -0400511/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700512 (no header, unspecified alignment)
513
Dave Barachc3799992016-08-15 11:12:27 -0400514 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700515 @param I vector index which will be valid upon return
516 @return V (value-result macro parameter)
517*/
518#define vec_validate(V,I) vec_validate_ha(V,I,0,0)
519
Dave Barachc3799992016-08-15 11:12:27 -0400520/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700521 (no header, specified alignment)
522
Dave Barachc3799992016-08-15 11:12:27 -0400523 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700524 @param I vector index which will be valid upon return
525 @param A alignment (may be zero)
526 @return V (value-result macro parameter)
527*/
528
529#define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
530
Dave Barachc3799992016-08-15 11:12:27 -0400531/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532 and initialize empty space (general version)
533
Dave Barachc3799992016-08-15 11:12:27 -0400534 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700535 @param I vector index which will be valid upon return
536 @param INIT initial value (can be a complex expression!)
537 @param H header size in bytes (may be zero)
538 @param A alignment (may be zero)
539 @return V (value-result macro parameter)
540*/
541#define vec_validate_init_empty_ha(V,I,INIT,H,A) \
542do { \
543 word _v(i) = (I); \
544 word _v(l) = vec_len (V); \
545 if (_v(i) >= _v(l)) \
546 { \
547 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
548 while (_v(l) <= _v(i)) \
549 { \
550 (V)[_v(l)] = (INIT); \
551 _v(l)++; \
552 } \
553 } \
554} while (0)
555
Dave Barachc3799992016-08-15 11:12:27 -0400556/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700557 and initialize empty space (no header, unspecified alignment)
558
Dave Barachc3799992016-08-15 11:12:27 -0400559 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700560 @param I vector index which will be valid upon return
561 @param INIT initial value (can be a complex expression!)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700562 @return V (value-result macro parameter)
563*/
564
565#define vec_validate_init_empty(V,I,INIT) \
566 vec_validate_init_empty_ha(V,I,INIT,0,0)
567
Dave Barachc3799992016-08-15 11:12:27 -0400568/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700569 and initialize empty space (no header, alignment alignment)
570
Dave Barachc3799992016-08-15 11:12:27 -0400571 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700572 @param I vector index which will be valid upon return
573 @param INIT initial value (can be a complex expression!)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700574 @param A alignment (may be zero)
575 @return V (value-result macro parameter)
576*/
Damjan Marion7d272182017-06-05 21:53:39 +0200577#define vec_validate_init_empty_aligned(V,I,INIT,A) \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700578 vec_validate_init_empty_ha(V,I,INIT,0,A)
579
Dave Barachc3799992016-08-15 11:12:27 -0400580/** \brief Add 1 element to end of vector (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700581
582 @param V pointer to a vector
583 @param E element to add
584 @param H header size in bytes (may be zero)
585 @param A alignment (may be zero)
586 @return V (value-result macro parameter)
587*/
588#define vec_add1_ha(V,E,H,A) \
589do { \
590 word _v(l) = vec_len (V); \
591 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
592 (V)[_v(l)] = (E); \
593} while (0)
594
Dave Barachc3799992016-08-15 11:12:27 -0400595/** \brief Add 1 element to end of vector (unspecified alignment).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700596
597 @param V pointer to a vector
598 @param E element to add
599 @return V (value-result macro parameter)
600*/
601#define vec_add1(V,E) vec_add1_ha(V,E,0,0)
602
Dave Barachc3799992016-08-15 11:12:27 -0400603/** \brief Add 1 element to end of vector (alignment specified).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700604
605 @param V pointer to a vector
606 @param E element to add
Ed Warnickecb9cada2015-12-08 15:45:58 -0700607 @param A alignment (may be zero)
608 @return V (value-result macro parameter)
609*/
610#define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
611
Dave Barachc3799992016-08-15 11:12:27 -0400612/** \brief Add N elements to end of vector V,
613 return pointer to new elements in P. (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700614
615 @param V pointer to a vector
616 @param P pointer to new vector element(s)
617 @param N number of elements to add
618 @param H header size in bytes (may be zero)
619 @param A alignment (may be zero)
620 @return V and P (value-result macro parameters)
621*/
622#define vec_add2_ha(V,P,N,H,A) \
623do { \
624 word _v(n) = (N); \
625 word _v(l) = vec_len (V); \
626 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
627 P = (V) + _v(l); \
628} while (0)
629
Dave Barachc3799992016-08-15 11:12:27 -0400630/** \brief Add N elements to end of vector V,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700631 return pointer to new elements in P. (no header, unspecified alignment)
632
633 @param V pointer to a vector
634 @param P pointer to new vector element(s)
635 @param N number of elements to add
636 @return V and P (value-result macro parameters)
637*/
638
639#define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
640
Dave Barachc3799992016-08-15 11:12:27 -0400641/** \brief Add N elements to end of vector V,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700642 return pointer to new elements in P. (no header, alignment specified)
643
644 @param V pointer to a vector
645 @param P pointer to new vector element(s)
646 @param N number of elements to add
647 @param A alignment (may be zero)
648 @return V and P (value-result macro parameters)
649*/
650
651#define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
652
Dave Barachc3799992016-08-15 11:12:27 -0400653/** \brief Add N elements to end of vector V (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700654
655 @param V pointer to a vector
656 @param E pointer to element(s) to add
657 @param N number of elements to add
658 @param H header size in bytes (may be zero)
659 @param A alignment (may be zero)
660 @return V (value-result macro parameter)
661*/
BenoƮt Ganne1a3e08a2021-02-11 19:46:43 +0100662#define vec_add_ha(V, E, N, H, A) \
663 do \
664 { \
665 word _v (n) = (N); \
666 if (PREDICT_TRUE (_v (n) > 0)) \
667 { \
668 word _v (l) = vec_len (V); \
669 V = _vec_resize ((V), _v (n), (_v (l) + _v (n)) * sizeof ((V)[0]), \
670 (H), (A)); \
671 clib_memcpy_fast ((V) + _v (l), (E), _v (n) * sizeof ((V)[0])); \
672 } \
673 } \
674 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700675
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
Dave Barachc3799992016-08-15 11:12:27 -0400695/** \brief Returns last element of a vector and decrements its length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696
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
Dave Barachc3799992016-08-15 11:12:27 -0400709/** \brief Set E to the last element of a vector, decrement vector length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700710 @param V pointer to a vector
711 @param E pointer to the last vector element
Dave Barachc3799992016-08-15 11:12:27 -0400712 @return E element removed from the end of the vector
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713 (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
Dave Barachc3799992016-08-15 11:12:27 -0400723/** \brief Insert N vector elements starting at element M,
724 initialize new elements (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700725
Dave Barachc3799992016-08-15 11:12:27 -0400726 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727 @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) \
735do { \
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])); \
Dave Barachb7b92992018-10-17 10:38:51 -0400747 clib_memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700748} while (0)
749
Dave Barachc3799992016-08-15 11:12:27 -0400750/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700751 initialize new elements to zero (general version)
752
Dave Barachc3799992016-08-15 11:12:27 -0400753 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700754 @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
Dave Barachc3799992016-08-15 11:12:27 -0400762/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700763 initialize new elements to zero (no header, unspecified alignment)
764
Dave Barachc3799992016-08-15 11:12:27 -0400765 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700766 @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
Dave Barachc3799992016-08-15 11:12:27 -0400772/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700773 initialize new elements to zero (no header, alignment specified)
774
Dave Barachc3799992016-08-15 11:12:27 -0400775 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700776 @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
Dave Barachc3799992016-08-15 11:12:27 -0400783/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784 initialize new elements (no header, unspecified alignment)
785
Dave Barachc3799992016-08-15 11:12:27 -0400786 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787 @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
Dave Barachc3799992016-08-15 11:12:27 -0400797/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700798 initialize new elements (no header, specified alignment)
799
Dave Barachc3799992016-08-15 11:12:27 -0400800 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700801 @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
Dave Barachc3799992016-08-15 11:12:27 -0400810/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700811 insert given elements (general version)
812
Dave Barachc3799992016-08-15 11:12:27 -0400813 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700814 @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
BenoƮt Ganne1a3e08a2021-02-11 19:46:43 +0100822#define vec_insert_elts_ha(V, E, N, M, H, A) \
823 do \
824 { \
825 word _v (n) = (N); \
826 if (PREDICT_TRUE (_v (n) > 0)) \
827 { \
828 word _v (l) = vec_len (V); \
829 word _v (m) = (M); \
830 V = _vec_resize ((V), _v (n), (_v (l) + _v (n)) * sizeof ((V)[0]), \
831 (H), (A)); \
832 ASSERT (_v (m) <= _v (l)); \
833 memmove ((V) + _v (m) + _v (n), (V) + _v (m), \
834 (_v (l) - _v (m)) * sizeof ((V)[0])); \
835 clib_memcpy_fast ((V) + _v (m), (E), _v (n) * sizeof ((V)[0])); \
836 } \
837 } \
838 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700839
Dave Barachc3799992016-08-15 11:12:27 -0400840/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700841 insert given elements (no header, unspecified alignment)
842
Dave Barachc3799992016-08-15 11:12:27 -0400843 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700844 @param E element(s) to insert
845 @param N number of elements to insert
846 @param M insertion point
847 @return V (value-result macro parameter)
848*/
849#define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
850
Dave Barachc3799992016-08-15 11:12:27 -0400851/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700852 insert given elements (no header, specified alignment)
853
Dave Barachc3799992016-08-15 11:12:27 -0400854 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700855 @param E element(s) to insert
856 @param N number of elements to insert
857 @param M insertion point
858 @param A alignment (may be zero)
859 @return V (value-result macro parameter)
860*/
861#define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
862
Dave Barachc3799992016-08-15 11:12:27 -0400863/** \brief Delete N elements starting at element M
Ed Warnickecb9cada2015-12-08 15:45:58 -0700864
865 @param V pointer to a vector
866 @param N number of elements to delete
867 @param M first element to delete
868 @return V (value-result macro parameter)
869*/
870#define vec_delete(V,N,M) \
871do { \
872 word _v(l) = vec_len (V); \
873 word _v(n) = (N); \
874 word _v(m) = (M); \
875 /* Copy over deleted elements. */ \
876 if (_v(l) - _v(n) - _v(m) > 0) \
877 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
878 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
879 /* Zero empty space at end (for future re-allocation). */ \
880 if (_v(n) > 0) \
Dave Barachb7b92992018-10-17 10:38:51 -0400881 clib_memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700882 _vec_len (V) -= _v(n); \
BenoƮt Ganne9fb6d402019-04-15 15:28:21 +0200883 CLIB_MEM_POISON(vec_end(V), _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700884} while (0)
885
886/** \brief Delete the element at index I
887
888 @param V pointer to a vector
889 @param I index to delete
890*/
891#define vec_del1(v,i) \
892do { \
893 uword _vec_del_l = _vec_len (v) - 1; \
894 uword _vec_del_i = (i); \
895 if (_vec_del_i < _vec_del_l) \
896 (v)[_vec_del_i] = (v)[_vec_del_l]; \
897 _vec_len (v) = _vec_del_l; \
BenoƮt Ganne9fb6d402019-04-15 15:28:21 +0200898 CLIB_MEM_POISON(vec_end(v), sizeof ((v)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700899} while (0)
900
901/** \brief Append v2 after v1. Result in v1.
902 @param V1 target vector
903 @param V2 vector to append
904*/
Dave Barachc3799992016-08-15 11:12:27 -0400905
BenoƮt Ganne1a3e08a2021-02-11 19:46:43 +0100906#define vec_append(v1, v2) \
907 do \
908 { \
909 uword _v (l1) = vec_len (v1); \
910 uword _v (l2) = vec_len (v2); \
911 \
912 if (PREDICT_TRUE (_v (l2) > 0)) \
913 { \
914 v1 = _vec_resize ((v1), _v (l2), \
915 (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, 0); \
916 clib_memcpy_fast ((v1) + _v (l1), (v2), \
917 _v (l2) * sizeof ((v2)[0])); \
918 } \
919 } \
920 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700921
922/** \brief Append v2 after v1. Result in v1. Specified alignment.
923 @param V1 target vector
924 @param V2 vector to append
925 @param align required alignment
926*/
Dave Barachc3799992016-08-15 11:12:27 -0400927
BenoƮt Ganne1a3e08a2021-02-11 19:46:43 +0100928#define vec_append_aligned(v1, v2, align) \
929 do \
930 { \
931 uword _v (l1) = vec_len (v1); \
932 uword _v (l2) = vec_len (v2); \
933 \
934 if (PREDICT_TRUE (_v (l2) > 0)) \
935 { \
936 v1 = _vec_resize ( \
937 (v1), _v (l2), (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, align); \
938 clib_memcpy_fast ((v1) + _v (l1), (v2), \
939 _v (l2) * sizeof ((v2)[0])); \
940 } \
941 } \
942 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700943
944/** \brief Prepend v2 before v1. Result in v1.
945 @param V1 target vector
946 @param V2 vector to prepend
947*/
948
BenoƮt Ganne1a3e08a2021-02-11 19:46:43 +0100949#define vec_prepend(v1, v2) \
950 do \
951 { \
952 uword _v (l1) = vec_len (v1); \
953 uword _v (l2) = vec_len (v2); \
954 \
955 if (PREDICT_TRUE (_v (l2) > 0)) \
956 { \
957 v1 = _vec_resize ((v1), _v (l2), \
958 (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, 0); \
959 memmove ((v1) + _v (l2), (v1), _v (l1) * sizeof ((v1)[0])); \
960 clib_memcpy_fast ((v1), (v2), _v (l2) * sizeof ((v2)[0])); \
961 } \
962 } \
963 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700964
965/** \brief Prepend v2 before v1. Result in v1. Specified alignment
966 @param V1 target vector
967 @param V2 vector to prepend
968 @param align required alignment
969*/
970
BenoƮt Ganne1a3e08a2021-02-11 19:46:43 +0100971#define vec_prepend_aligned(v1, v2, align) \
972 do \
973 { \
974 uword _v (l1) = vec_len (v1); \
975 uword _v (l2) = vec_len (v2); \
976 \
977 if (PREDICT_TRUE (_v (l2) > 0)) \
978 { \
979 v1 = _vec_resize ( \
980 (v1), _v (l2), (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, align); \
981 memmove ((v1) + _v (l2), (v1), _v (l1) * sizeof ((v1)[0])); \
982 clib_memcpy_fast ((v1), (v2), _v (l2) * sizeof ((v2)[0])); \
983 } \
984 } \
985 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700986
987/** \brief Zero all vector elements. Null-pointer tolerant.
988 @param var Vector to zero
989*/
990#define vec_zero(var) \
991do { \
992 if (var) \
Dave Barachb7b92992018-10-17 10:38:51 -0400993 clib_memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700994} while (0)
995
996/** \brief Set all vector elements to given value. Null-pointer tolerant.
997 @param v vector to set
998 @param val value for each vector element
999*/
1000#define vec_set(v,val) \
1001do { \
1002 word _v(i); \
1003 __typeof__ ((v)[0]) _val = (val); \
1004 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
1005 (v)[_v(i)] = _val; \
1006} while (0)
1007
1008#ifdef CLIB_UNIX
1009#include <stdlib.h> /* for qsort */
1010#endif
1011
1012/** \brief Compare two vectors, not NULL-pointer tolerant
1013
1014 @param v1 Pointer to a vector
1015 @param v2 Pointer to a vector
1016 @return 1 if equal, 0 if unequal
1017*/
1018#define vec_is_equal(v1,v2) \
1019 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
1020
1021/** \brief Compare two vectors (only applicable to vectors of signed numbers).
Dave Barachc3799992016-08-15 11:12:27 -04001022 Used in qsort compare functions.
1023
Ed Warnickecb9cada2015-12-08 15:45:58 -07001024 @param v1 Pointer to a vector
1025 @param v2 Pointer to a vector
1026 @return -1, 0, +1
1027*/
1028#define vec_cmp(v1,v2) \
1029({ \
1030 word _v(i), _v(cmp), _v(l); \
1031 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
1032 _v(cmp) = 0; \
1033 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
1034 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
1035 if (_v(cmp)) \
1036 break; \
1037 } \
1038 if (_v(cmp) == 0 && _v(l) > 0) \
1039 _v(cmp) = vec_len(v1) - vec_len(v2); \
1040 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
1041})
1042
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001043/** \brief Search a vector for the index of the entry that matches.
1044
Dave Wallace64b3cc22019-04-05 10:30:44 -04001045 @param v Pointer to a vector
1046 @param E Entry to match
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001047 @return index of match or ~0
1048*/
1049#define vec_search(v,E) \
1050({ \
1051 word _v(i) = 0; \
1052 while (_v(i) < vec_len(v)) \
1053 { \
Andrew Yourtchenkof908a032017-06-20 12:26:23 +02001054 if ((v)[_v(i)] == E) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001055 break; \
1056 _v(i)++; \
1057 } \
1058 if (_v(i) == vec_len(v)) \
1059 _v(i) = ~0; \
1060 _v(i); \
1061})
1062
Neale Ranns947ea622018-06-07 23:48:20 -07001063/** \brief Search a vector for the index of the entry that matches.
1064
Dave Wallace64b3cc22019-04-05 10:30:44 -04001065 @param v Pointer to a vector
1066 @param E Pointer to entry to match
Neale Ranns947ea622018-06-07 23:48:20 -07001067 @param fn Comparison function !0 => match
1068 @return index of match or ~0
1069*/
1070#define vec_search_with_function(v,E,fn) \
1071({ \
1072 word _v(i) = 0; \
1073 while (_v(i) < vec_len(v)) \
1074 { \
1075 if (0 != fn(&(v)[_v(i)], (E))) \
1076 break; \
1077 _v(i)++; \
1078 } \
1079 if (_v(i) == vec_len(v)) \
1080 _v(i) = ~0; \
1081 _v(i); \
1082})
1083
Ed Warnickecb9cada2015-12-08 15:45:58 -07001084/** \brief Sort a vector using the supplied element comparison function
1085
Dave Barachf593b572020-04-24 16:07:37 -04001086 Does not depend on the underlying implementation to deal correctly
1087 with null, zero-long, or 1-long vectors
1088
Ed Warnickecb9cada2015-12-08 15:45:58 -07001089 @param vec vector to sort
1090 @param f comparison function
1091*/
Dave Barachf593b572020-04-24 16:07:37 -04001092#define vec_sort_with_function(vec,f) \
1093do { \
1094 if (vec_len (vec) > 1) \
1095 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -07001096} while (0)
1097
1098/** \brief Make a vector containing a NULL terminated c-string.
1099
Dave Barachc3799992016-08-15 11:12:27 -04001100 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001101 @param S pointer to string buffer.
1102 @param L string length (NOT including the terminating NULL; a la strlen())
1103*/
1104#define vec_validate_init_c_string(V, S, L) \
1105 do { \
1106 vec_reset_length (V); \
1107 vec_validate ((V), (L)); \
1108 if ((S) && (L)) \
Dave Barach178cf492018-11-13 16:34:13 -05001109 clib_memcpy_fast ((V), (S), (L)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -07001110 (V)[(L)] = 0; \
1111 } while (0)
1112
1113
Chris Lukeb5850972016-05-03 16:34:59 -04001114/** \brief Test whether a vector is a NULL terminated c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001115
Dave Barachc3799992016-08-15 11:12:27 -04001116 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001117 @return BOOLEAN indicating if the vector c-string is null terminated.
1118*/
1119#define vec_c_string_is_terminated(V) \
1120 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
1121
Chris Lukeb5850972016-05-03 16:34:59 -04001122/** \brief (If necessary) NULL terminate a vector containing a c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001123
Dave Barachc3799992016-08-15 11:12:27 -04001124 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001125 @return V (value-result macro parameter)
1126*/
1127#define vec_terminate_c_string(V) \
1128 do { \
1129 u32 vl = vec_len ((V)); \
1130 if (!vec_c_string_is_terminated(V)) \
1131 { \
1132 vec_validate ((V), vl); \
1133 (V)[vl] = 0; \
1134 } \
1135 } while (0)
1136
1137#endif /* included_vec_h */
1138
Dave Barachc3799992016-08-15 11:12:27 -04001139
1140/*
1141 * fd.io coding-style-patch-verification: ON
1142 *
1143 * Local Variables:
1144 * eval: (c-set-style "gnu")
1145 * End:
1146 */