blob: df913c2b144b6453fcf755842236e70fb77bd6c0 [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; \
122 _V = _vec_resize_inline(V,L,DB,HB,clib_max((__alignof__((V)[0])),(A)),(S)); \
123 _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
Dave Barachc3799992016-08-15 11:12:27 -0400212/** \brief Predicate function, says whether the supplied vector is a clib heap
213 object (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214
215 @param v pointer to a vector
216 @param header_bytes vector header size in bytes (may be zero)
217 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400218*/
219uword clib_mem_is_vec_h (void *v, uword header_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700220
221
Dave Barachc3799992016-08-15 11:12:27 -0400222/** \brief Predicate function, says whether the supplied vector is a clib heap
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223 object
224
225 @param v pointer to a vector
226 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400227*/
228always_inline uword
229clib_mem_is_vec (void *v)
230{
231 return clib_mem_is_vec_h (v, 0);
232}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233
234/* Local variable naming macro (prevents collisions with other macro naming). */
235#define _v(var) _vec_##var
236
237/** \brief Resize a vector (general version).
238 Add N elements to end of given vector V, return pointer to start of vector.
239 Vector will have room for H header bytes and will have user's data aligned
240 at alignment A (rounded to next power of 2).
241
242 @param V pointer to a vector
243 @param N number of elements to add
244 @param H header size in bytes (may be zero)
245 @param A alignment (may be zero)
Dave Baracha690fdb2020-01-21 12:34:55 -0500246 @param S numa_id (may be zero)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700247 @return V (value-result macro parameter)
248*/
249
Dave Baracha690fdb2020-01-21 12:34:55 -0500250#define vec_resize_has(V,N,H,A,S) \
251do { \
252 word _v(n) = (N); \
253 word _v(l) = vec_len (V); \
254 V = _vec_resize_numa ((V), _v(n), \
255 (_v(l) + _v(n)) * sizeof ((V)[0]), \
256 (H), (A),(S)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700257} while (0)
258
Dave Baracha690fdb2020-01-21 12:34:55 -0500259/** \brief Resize a vector (less general version).
260 Add N elements to end of given vector V, return pointer to start of vector.
261 Vector will have room for H header bytes and will have user's data aligned
262 at alignment A (rounded to next power of 2).
263
264 @param V pointer to a vector
265 @param N number of elements to add
266 @param H header size in bytes (may be zero)
267 @param A alignment (may be zero)
268 @return V (value-result macro parameter)
269*/
270#define vec_resize_ha(V,N,H,A) vec_resize_has(V,N,H,A,VEC_NUMA_UNSPECIFIED)
271
Ed Warnickecb9cada2015-12-08 15:45:58 -0700272/** \brief Resize a vector (no header, unspecified alignment)
273 Add N elements to end of given vector V, return pointer to start of vector.
274 Vector will have room for H header bytes and will have user's data aligned
275 at alignment A (rounded to next power of 2).
276
277 @param V pointer to a vector
278 @param N number of elements to add
279 @return V (value-result macro parameter)
280*/
281#define vec_resize(V,N) vec_resize_ha(V,N,0,0)
282
283/** \brief Resize a vector (no header, alignment specified).
284 Add N elements to end of given vector V, return pointer to start of vector.
285 Vector will have room for H header bytes and will have user's data aligned
286 at alignment A (rounded to next power of 2).
287
288 @param V pointer to a vector
289 @param N number of elements to add
290 @param A alignment (may be zero)
291 @return V (value-result macro parameter)
292*/
293
294#define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
295
Dave Barachc3799992016-08-15 11:12:27 -0400296/** \brief Allocate space for N more elements
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297
298 @param V pointer to a vector
299 @param N number of elements to add
300 @param H header size in bytes (may be zero)
301 @param A alignment (may be zero)
302 @return V (value-result macro parameter)
303*/
304
305#define vec_alloc_ha(V,N,H,A) \
306do { \
307 uword _v(l) = vec_len (V); \
308 vec_resize_ha (V, N, H, A); \
309 _vec_len (V) = _v(l); \
310} while (0)
311
Dave Barachc3799992016-08-15 11:12:27 -0400312/** \brief Allocate space for N more elements
313 (no header, unspecified alignment)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314
315 @param V pointer to a vector
316 @param N number of elements to add
317 @return V (value-result macro parameter)
318*/
319#define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
320
321/** \brief Allocate space for N more elements (no header, given alignment)
322 @param V pointer to a vector
323 @param N number of elements to add
324 @param A alignment (may be zero)
325 @return V (value-result macro parameter)
326*/
327
328#define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
329
330/** \brief Create new vector of given type and length (general version).
331 @param T type of elements in new vector
332 @param N number of elements to add
333 @param H header size in bytes (may be zero)
334 @param A alignment (may be zero)
335 @return V new vector
336*/
Andreas Schultzc458c492020-03-26 14:18:52 +0000337#define vec_new_ha(T,N,H,A) \
338({ \
339 word _v(n) = (N); \
340 (T *)_vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700341})
342
Dave Barachc3799992016-08-15 11:12:27 -0400343/** \brief Create new vector of given type and length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700344 (unspecified alignment, no header).
345
346 @param T type of elements in new vector
347 @param N number of elements to add
348 @return V new vector
349*/
350#define vec_new(T,N) vec_new_ha(T,N,0,0)
Dave Barachc3799992016-08-15 11:12:27 -0400351/** \brief Create new vector of given type and length
352 (alignment specified, no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353
354 @param T type of elements in new vector
355 @param N number of elements to add
356 @param A alignment (may be zero)
357 @return V new vector
358*/
359#define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
360
361/** \brief Free vector's memory (general version)
362
363 @param V pointer to a vector
364 @param H size of header in bytes
365 @return V (value-result parameter, V=0)
366*/
367#define vec_free_h(V,H) \
368do { \
369 if (V) \
370 { \
371 clib_mem_free (vec_header ((V), (H))); \
372 V = 0; \
373 } \
374} while (0)
375
Dave Barachc3799992016-08-15 11:12:27 -0400376/** \brief Free vector's memory (no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377 @param V pointer to a vector
378 @return V (value-result parameter, V=0)
379*/
380#define vec_free(V) vec_free_h(V,0)
381
382/**\brief Free vector user header (syntactic sugar)
383 @param h vector header
384 @void
385*/
386#define vec_free_header(h) clib_mem_free (h)
387
388/** \brief Return copy of vector (general version).
389
390 @param V pointer to a vector
391 @param H size of header in bytes
392 @param A alignment (may be zero)
Dave Baracha690fdb2020-01-21 12:34:55 -0500393 @param S numa (may be VEC_NUMA_UNSPECIFIED)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394
395 @return Vdup copy of vector
396*/
397
Dave Baracha690fdb2020-01-21 12:34:55 -0500398#define vec_dup_ha_numa(V,H,A,S) \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399({ \
400 __typeof__ ((V)[0]) * _v(v) = 0; \
401 uword _v(l) = vec_len (V); \
402 if (_v(l) > 0) \
403 { \
Dave Baracha690fdb2020-01-21 12:34:55 -0500404 vec_resize_has (_v(v), _v(l), (H), (A), (S)); \
Dave Barach178cf492018-11-13 16:34:13 -0500405 clib_memcpy_fast (_v(v), (V), _v(l) * sizeof ((V)[0]));\
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406 } \
407 _v(v); \
408})
409
Dave Baracha690fdb2020-01-21 12:34:55 -0500410/** \brief Return copy of vector (VEC_NUMA_UNSPECIFIED).
411
412 @param V pointer to a vector
413 @param H size of header in bytes
414 @param A alignment (may be zero)
415
416 @return Vdup copy of vector
417*/
418#define vec_dup_ha(V,H,A) \
419 vec_dup_ha_numa(V,H,A,VEC_NUMA_UNSPECIFIED)
420
421
Ed Warnickecb9cada2015-12-08 15:45:58 -0700422/** \brief Return copy of vector (no header, no alignment)
423
424 @param V pointer to a vector
425 @return Vdup copy of vector
426*/
427#define vec_dup(V) vec_dup_ha(V,0,0)
428
429/** \brief Return copy of vector (no header, alignment specified).
430
431 @param V pointer to a vector
432 @param A alignment (may be zero)
433
434 @return Vdup copy of vector
435*/
436#define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
437
438/** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
439 sizeof(DST[0])
440
Dave Barachc3799992016-08-15 11:12:27 -0400441 @param DST destination
Ed Warnickecb9cada2015-12-08 15:45:58 -0700442 @param SRC source
443*/
Dave Barach178cf492018-11-13 16:34:13 -0500444#define vec_copy(DST,SRC) clib_memcpy_fast (DST, SRC, vec_len (DST) * \
Damjan Marionf1213b82016-03-13 02:22:06 +0100445 sizeof ((DST)[0]))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700446
Dave Barachc3799992016-08-15 11:12:27 -0400447/** \brief Clone a vector. Make a new vector with the
Ed Warnickecb9cada2015-12-08 15:45:58 -0700448 same size as a given vector but possibly with a different type.
449
450 @param NEW_V pointer to new vector
451 @param OLD_V pointer to old vector
452*/
453#define vec_clone(NEW_V,OLD_V) \
454do { \
455 (NEW_V) = 0; \
456 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
457 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
458} while (0)
459
460/** \brief Make sure vector is long enough for given index (general version).
461
Dave Barachc3799992016-08-15 11:12:27 -0400462 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700463 @param I vector index which will be valid upon return
464 @param H header size in bytes (may be zero)
465 @param A alignment (may be zero)
Dave Baracha690fdb2020-01-21 12:34:55 -0500466 @param N numa_id (may be zero)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700467 @return V (value-result macro parameter)
468*/
469
Dave Baracha690fdb2020-01-21 12:34:55 -0500470#define vec_validate_han(V,I,H,A,N) \
471do { \
472 void *oldheap; \
473 STATIC_ASSERT(A==0 || ((A % sizeof(V[0]))==0) \
474 || ((sizeof(V[0]) % A) == 0), \
475 "vector validate aligned on incorrectly sized object"); \
476 word _v(i) = (I); \
477 word _v(l) = vec_len (V); \
478 if (_v(i) >= _v(l)) \
479 { \
480 /* switch to the per-numa heap if directed */ \
481 if (PREDICT_FALSE(N != VEC_NUMA_UNSPECIFIED)) \
482 { \
483 oldheap = clib_mem_get_per_cpu_heap(); \
484 clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap(N)); \
485 } \
486 \
487 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
488 /* Must zero new space since user may have previously \
489 used e.g. _vec_len (v) -= 10 */ \
490 clib_memset ((V) + _v(l), 0, \
491 (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
492 /* Switch back to the global heap */ \
493 if (PREDICT_FALSE (N != VEC_NUMA_UNSPECIFIED)) \
494 clib_mem_set_per_cpu_heap (oldheap); \
495 } \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700496} while (0)
497
Dave Baracha690fdb2020-01-21 12:34:55 -0500498#define vec_validate_ha(V,I,H,A) vec_validate_han(V,I,H,A,VEC_NUMA_UNSPECIFIED)
499
Dave Barachc3799992016-08-15 11:12:27 -0400500/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700501 (no header, unspecified alignment)
502
Dave Barachc3799992016-08-15 11:12:27 -0400503 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700504 @param I vector index which will be valid upon return
505 @return V (value-result macro parameter)
506*/
507#define vec_validate(V,I) vec_validate_ha(V,I,0,0)
508
Dave Barachc3799992016-08-15 11:12:27 -0400509/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510 (no header, specified alignment)
511
Dave Barachc3799992016-08-15 11:12:27 -0400512 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513 @param I vector index which will be valid upon return
514 @param A alignment (may be zero)
515 @return V (value-result macro parameter)
516*/
517
518#define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
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 and initialize empty space (general version)
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 INIT initial value (can be a complex expression!)
526 @param H header size in bytes (may be zero)
527 @param A alignment (may be zero)
528 @return V (value-result macro parameter)
529*/
530#define vec_validate_init_empty_ha(V,I,INIT,H,A) \
531do { \
532 word _v(i) = (I); \
533 word _v(l) = vec_len (V); \
534 if (_v(i) >= _v(l)) \
535 { \
536 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
537 while (_v(l) <= _v(i)) \
538 { \
539 (V)[_v(l)] = (INIT); \
540 _v(l)++; \
541 } \
542 } \
543} while (0)
544
Dave Barachc3799992016-08-15 11:12:27 -0400545/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546 and initialize empty space (no header, unspecified alignment)
547
Dave Barachc3799992016-08-15 11:12:27 -0400548 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549 @param I vector index which will be valid upon return
550 @param INIT initial value (can be a complex expression!)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700551 @return V (value-result macro parameter)
552*/
553
554#define vec_validate_init_empty(V,I,INIT) \
555 vec_validate_init_empty_ha(V,I,INIT,0,0)
556
Dave Barachc3799992016-08-15 11:12:27 -0400557/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700558 and initialize empty space (no header, alignment alignment)
559
Dave Barachc3799992016-08-15 11:12:27 -0400560 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700561 @param I vector index which will be valid upon return
562 @param INIT initial value (can be a complex expression!)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700563 @param A alignment (may be zero)
564 @return V (value-result macro parameter)
565*/
Damjan Marion7d272182017-06-05 21:53:39 +0200566#define vec_validate_init_empty_aligned(V,I,INIT,A) \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700567 vec_validate_init_empty_ha(V,I,INIT,0,A)
568
Dave Barachc3799992016-08-15 11:12:27 -0400569/** \brief Add 1 element to end of vector (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700570
571 @param V pointer to a vector
572 @param E element to add
573 @param H header size in bytes (may be zero)
574 @param A alignment (may be zero)
575 @return V (value-result macro parameter)
576*/
577#define vec_add1_ha(V,E,H,A) \
578do { \
579 word _v(l) = vec_len (V); \
580 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
581 (V)[_v(l)] = (E); \
582} while (0)
583
Dave Barachc3799992016-08-15 11:12:27 -0400584/** \brief Add 1 element to end of vector (unspecified alignment).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700585
586 @param V pointer to a vector
587 @param E element to add
588 @return V (value-result macro parameter)
589*/
590#define vec_add1(V,E) vec_add1_ha(V,E,0,0)
591
Dave Barachc3799992016-08-15 11:12:27 -0400592/** \brief Add 1 element to end of vector (alignment specified).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700593
594 @param V pointer to a vector
595 @param E element to add
Ed Warnickecb9cada2015-12-08 15:45:58 -0700596 @param A alignment (may be zero)
597 @return V (value-result macro parameter)
598*/
599#define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
600
Dave Barachc3799992016-08-15 11:12:27 -0400601/** \brief Add N elements to end of vector V,
602 return pointer to new elements in P. (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700603
604 @param V pointer to a vector
605 @param P pointer to new vector element(s)
606 @param N number of elements to add
607 @param H header size in bytes (may be zero)
608 @param A alignment (may be zero)
609 @return V and P (value-result macro parameters)
610*/
611#define vec_add2_ha(V,P,N,H,A) \
612do { \
613 word _v(n) = (N); \
614 word _v(l) = vec_len (V); \
615 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
616 P = (V) + _v(l); \
617} while (0)
618
Dave Barachc3799992016-08-15 11:12:27 -0400619/** \brief Add N elements to end of vector V,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700620 return pointer to new elements in P. (no header, unspecified alignment)
621
622 @param V pointer to a vector
623 @param P pointer to new vector element(s)
624 @param N number of elements to add
625 @return V and P (value-result macro parameters)
626*/
627
628#define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,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, alignment specified)
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 @param A alignment (may be zero)
637 @return V and P (value-result macro parameters)
638*/
639
640#define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
641
Dave Barachc3799992016-08-15 11:12:27 -0400642/** \brief Add N elements to end of vector V (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700643
644 @param V pointer to a vector
645 @param E pointer to element(s) to add
646 @param N number of elements to add
647 @param H header size in bytes (may be zero)
648 @param A alignment (may be zero)
649 @return V (value-result macro parameter)
650*/
651#define vec_add_ha(V,E,N,H,A) \
652do { \
653 word _v(n) = (N); \
654 word _v(l) = vec_len (V); \
655 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
Dave Barach178cf492018-11-13 16:34:13 -0500656 clib_memcpy_fast ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700657} while (0)
658
659/** \brief Add N elements to end of vector V (no header, unspecified alignment)
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 @return V (value-result macro parameter)
665*/
666#define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
667
668/** \brief Add N elements to end of vector V (no header, specified alignment)
669
670 @param V pointer to a vector
671 @param E pointer to element(s) to add
672 @param N number of elements to add
673 @param A alignment (may be zero)
674 @return V (value-result macro parameter)
675*/
676#define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
677
Dave Barachc3799992016-08-15 11:12:27 -0400678/** \brief Returns last element of a vector and decrements its length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700679
680 @param V pointer to a vector
681 @return E element removed from the end of the vector
682*/
683#define vec_pop(V) \
684({ \
685 uword _v(l) = vec_len (V); \
686 ASSERT (_v(l) > 0); \
687 _v(l) -= 1; \
688 _vec_len (V) = _v (l); \
689 (V)[_v(l)]; \
690})
691
Dave Barachc3799992016-08-15 11:12:27 -0400692/** \brief Set E to the last element of a vector, decrement vector length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700693 @param V pointer to a vector
694 @param E pointer to the last vector element
Dave Barachc3799992016-08-15 11:12:27 -0400695 @return E element removed from the end of the vector
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696 (value-result macro parameter
697*/
698
699#define vec_pop2(V,E) \
700({ \
701 uword _v(l) = vec_len (V); \
702 if (_v(l) > 0) (E) = vec_pop (V); \
703 _v(l) > 0; \
704})
705
Dave Barachc3799992016-08-15 11:12:27 -0400706/** \brief Insert N vector elements starting at element M,
707 initialize new elements (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700708
Dave Barachc3799992016-08-15 11:12:27 -0400709 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700710 @param N number of elements to insert
711 @param M insertion point
712 @param INIT initial value (can be a complex expression!)
713 @param H header size in bytes (may be zero)
714 @param A alignment (may be zero)
715 @return V (value-result macro parameter)
716*/
717#define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
718do { \
719 word _v(l) = vec_len (V); \
720 word _v(n) = (N); \
721 word _v(m) = (M); \
722 V = _vec_resize ((V), \
723 _v(n), \
724 (_v(l) + _v(n))*sizeof((V)[0]), \
725 (H), (A)); \
726 ASSERT (_v(m) <= _v(l)); \
727 memmove ((V) + _v(m) + _v(n), \
728 (V) + _v(m), \
729 (_v(l) - _v(m)) * sizeof ((V)[0])); \
Dave Barachb7b92992018-10-17 10:38:51 -0400730 clib_memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700731} while (0)
732
Dave Barachc3799992016-08-15 11:12:27 -0400733/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700734 initialize new elements to zero (general version)
735
Dave Barachc3799992016-08-15 11:12:27 -0400736 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700737 @param N number of elements to insert
738 @param M insertion point
739 @param H header size in bytes (may be zero)
740 @param A alignment (may be zero)
741 @return V (value-result macro parameter)
742*/
743#define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
744
Dave Barachc3799992016-08-15 11:12:27 -0400745/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700746 initialize new elements to zero (no header, unspecified alignment)
747
Dave Barachc3799992016-08-15 11:12:27 -0400748 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700749 @param N number of elements to insert
750 @param M insertion point
751 @return V (value-result macro parameter)
752*/
753#define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
754
Dave Barachc3799992016-08-15 11:12:27 -0400755/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700756 initialize new elements to zero (no header, alignment specified)
757
Dave Barachc3799992016-08-15 11:12:27 -0400758 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700759 @param N number of elements to insert
760 @param M insertion point
761 @param A alignment (may be zero)
762 @return V (value-result macro parameter)
763*/
764#define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
765
Dave Barachc3799992016-08-15 11:12:27 -0400766/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700767 initialize new elements (no header, unspecified alignment)
768
Dave Barachc3799992016-08-15 11:12:27 -0400769 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700770 @param N number of elements to insert
771 @param M insertion point
772 @param INIT initial value (can be a complex expression!)
773 @return V (value-result macro parameter)
774*/
775
776#define vec_insert_init_empty(V,N,M,INIT) \
777 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
778/* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
779
Dave Barachc3799992016-08-15 11:12:27 -0400780/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700781 initialize new elements (no header, specified alignment)
782
Dave Barachc3799992016-08-15 11:12:27 -0400783 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784 @param N number of elements to insert
785 @param M insertion point
786 @param INIT initial value (can be a complex expression!)
787 @param A alignment (may be zero)
788 @return V (value-result macro parameter)
789*/
790#define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
791 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
792
Dave Barachc3799992016-08-15 11:12:27 -0400793/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700794 insert given elements (general version)
795
Dave Barachc3799992016-08-15 11:12:27 -0400796 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700797 @param E element(s) to insert
798 @param N number of elements to insert
799 @param M insertion point
800 @param H header size in bytes (may be zero)
801 @param A alignment (may be zero)
802 @return V (value-result macro parameter)
803*/
804
805#define vec_insert_elts_ha(V,E,N,M,H,A) \
806do { \
807 word _v(l) = vec_len (V); \
808 word _v(n) = (N); \
809 word _v(m) = (M); \
810 V = _vec_resize ((V), \
811 _v(n), \
812 (_v(l) + _v(n))*sizeof((V)[0]), \
813 (H), (A)); \
814 ASSERT (_v(m) <= _v(l)); \
815 memmove ((V) + _v(m) + _v(n), \
816 (V) + _v(m), \
817 (_v(l) - _v(m)) * sizeof ((V)[0])); \
Dave Barach178cf492018-11-13 16:34:13 -0500818 clib_memcpy_fast ((V) + _v(m), (E), \
Damjan Marionf1213b82016-03-13 02:22:06 +0100819 _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700820} while (0)
821
Dave Barachc3799992016-08-15 11:12:27 -0400822/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700823 insert given elements (no header, unspecified alignment)
824
Dave Barachc3799992016-08-15 11:12:27 -0400825 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700826 @param E element(s) to insert
827 @param N number of elements to insert
828 @param M insertion point
829 @return V (value-result macro parameter)
830*/
831#define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
832
Dave Barachc3799992016-08-15 11:12:27 -0400833/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700834 insert given elements (no header, specified alignment)
835
Dave Barachc3799992016-08-15 11:12:27 -0400836 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700837 @param E element(s) to insert
838 @param N number of elements to insert
839 @param M insertion point
840 @param A alignment (may be zero)
841 @return V (value-result macro parameter)
842*/
843#define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
844
Dave Barachc3799992016-08-15 11:12:27 -0400845/** \brief Delete N elements starting at element M
Ed Warnickecb9cada2015-12-08 15:45:58 -0700846
847 @param V pointer to a vector
848 @param N number of elements to delete
849 @param M first element to delete
850 @return V (value-result macro parameter)
851*/
852#define vec_delete(V,N,M) \
853do { \
854 word _v(l) = vec_len (V); \
855 word _v(n) = (N); \
856 word _v(m) = (M); \
857 /* Copy over deleted elements. */ \
858 if (_v(l) - _v(n) - _v(m) > 0) \
859 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
860 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
861 /* Zero empty space at end (for future re-allocation). */ \
862 if (_v(n) > 0) \
Dave Barachb7b92992018-10-17 10:38:51 -0400863 clib_memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700864 _vec_len (V) -= _v(n); \
Benoît Ganne9fb6d402019-04-15 15:28:21 +0200865 CLIB_MEM_POISON(vec_end(V), _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700866} while (0)
867
868/** \brief Delete the element at index I
869
870 @param V pointer to a vector
871 @param I index to delete
872*/
873#define vec_del1(v,i) \
874do { \
875 uword _vec_del_l = _vec_len (v) - 1; \
876 uword _vec_del_i = (i); \
877 if (_vec_del_i < _vec_del_l) \
878 (v)[_vec_del_i] = (v)[_vec_del_l]; \
879 _vec_len (v) = _vec_del_l; \
Benoît Ganne9fb6d402019-04-15 15:28:21 +0200880 CLIB_MEM_POISON(vec_end(v), sizeof ((v)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700881} while (0)
882
883/** \brief Append v2 after v1. Result in v1.
884 @param V1 target vector
885 @param V2 vector to append
886*/
Dave Barachc3799992016-08-15 11:12:27 -0400887
Ed Warnickecb9cada2015-12-08 15:45:58 -0700888#define vec_append(v1,v2) \
889do { \
890 uword _v(l1) = vec_len (v1); \
891 uword _v(l2) = vec_len (v2); \
892 \
893 v1 = _vec_resize ((v1), _v(l2), \
894 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
Dave Barach178cf492018-11-13 16:34:13 -0500895 clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700896} while (0)
897
898/** \brief Append v2 after v1. Result in v1. Specified alignment.
899 @param V1 target vector
900 @param V2 vector to append
901 @param align required alignment
902*/
Dave Barachc3799992016-08-15 11:12:27 -0400903
Ed Warnickecb9cada2015-12-08 15:45:58 -0700904#define vec_append_aligned(v1,v2,align) \
905do { \
906 uword _v(l1) = vec_len (v1); \
907 uword _v(l2) = vec_len (v2); \
908 \
909 v1 = _vec_resize ((v1), _v(l2), \
910 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
Dave Barach178cf492018-11-13 16:34:13 -0500911 clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700912} while (0)
913
914/** \brief Prepend v2 before v1. Result in v1.
915 @param V1 target vector
916 @param V2 vector to prepend
917*/
918
919#define vec_prepend(v1,v2) \
920do { \
921 uword _v(l1) = vec_len (v1); \
922 uword _v(l2) = vec_len (v2); \
923 \
924 v1 = _vec_resize ((v1), _v(l2), \
925 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
926 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
Dave Barach178cf492018-11-13 16:34:13 -0500927 clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700928} while (0)
929
930/** \brief Prepend v2 before v1. Result in v1. Specified alignment
931 @param V1 target vector
932 @param V2 vector to prepend
933 @param align required alignment
934*/
935
936#define vec_prepend_aligned(v1,v2,align) \
937do { \
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, align); \
943 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
Dave Barach178cf492018-11-13 16:34:13 -0500944 clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700945} while (0)
946
947
948/** \brief Zero all vector elements. Null-pointer tolerant.
949 @param var Vector to zero
950*/
951#define vec_zero(var) \
952do { \
953 if (var) \
Dave Barachb7b92992018-10-17 10:38:51 -0400954 clib_memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700955} while (0)
956
957/** \brief Set all vector elements to given value. Null-pointer tolerant.
958 @param v vector to set
959 @param val value for each vector element
960*/
961#define vec_set(v,val) \
962do { \
963 word _v(i); \
964 __typeof__ ((v)[0]) _val = (val); \
965 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
966 (v)[_v(i)] = _val; \
967} while (0)
968
969#ifdef CLIB_UNIX
970#include <stdlib.h> /* for qsort */
971#endif
972
973/** \brief Compare two vectors, not NULL-pointer tolerant
974
975 @param v1 Pointer to a vector
976 @param v2 Pointer to a vector
977 @return 1 if equal, 0 if unequal
978*/
979#define vec_is_equal(v1,v2) \
980 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
981
982/** \brief Compare two vectors (only applicable to vectors of signed numbers).
Dave Barachc3799992016-08-15 11:12:27 -0400983 Used in qsort compare functions.
984
Ed Warnickecb9cada2015-12-08 15:45:58 -0700985 @param v1 Pointer to a vector
986 @param v2 Pointer to a vector
987 @return -1, 0, +1
988*/
989#define vec_cmp(v1,v2) \
990({ \
991 word _v(i), _v(cmp), _v(l); \
992 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
993 _v(cmp) = 0; \
994 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
995 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
996 if (_v(cmp)) \
997 break; \
998 } \
999 if (_v(cmp) == 0 && _v(l) > 0) \
1000 _v(cmp) = vec_len(v1) - vec_len(v2); \
1001 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
1002})
1003
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001004/** \brief Search a vector for the index of the entry that matches.
1005
Dave Wallace64b3cc22019-04-05 10:30:44 -04001006 @param v Pointer to a vector
1007 @param E Entry to match
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001008 @return index of match or ~0
1009*/
1010#define vec_search(v,E) \
1011({ \
1012 word _v(i) = 0; \
1013 while (_v(i) < vec_len(v)) \
1014 { \
Andrew Yourtchenkof908a032017-06-20 12:26:23 +02001015 if ((v)[_v(i)] == E) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001016 break; \
1017 _v(i)++; \
1018 } \
1019 if (_v(i) == vec_len(v)) \
1020 _v(i) = ~0; \
1021 _v(i); \
1022})
1023
Neale Ranns947ea622018-06-07 23:48:20 -07001024/** \brief Search a vector for the index of the entry that matches.
1025
Dave Wallace64b3cc22019-04-05 10:30:44 -04001026 @param v Pointer to a vector
1027 @param E Pointer to entry to match
Neale Ranns947ea622018-06-07 23:48:20 -07001028 @param fn Comparison function !0 => match
1029 @return index of match or ~0
1030*/
1031#define vec_search_with_function(v,E,fn) \
1032({ \
1033 word _v(i) = 0; \
1034 while (_v(i) < vec_len(v)) \
1035 { \
1036 if (0 != fn(&(v)[_v(i)], (E))) \
1037 break; \
1038 _v(i)++; \
1039 } \
1040 if (_v(i) == vec_len(v)) \
1041 _v(i) = ~0; \
1042 _v(i); \
1043})
1044
Ed Warnickecb9cada2015-12-08 15:45:58 -07001045/** \brief Sort a vector using the supplied element comparison function
1046
Dave Barachf593b572020-04-24 16:07:37 -04001047 Does not depend on the underlying implementation to deal correctly
1048 with null, zero-long, or 1-long vectors
1049
Ed Warnickecb9cada2015-12-08 15:45:58 -07001050 @param vec vector to sort
1051 @param f comparison function
1052*/
Dave Barachf593b572020-04-24 16:07:37 -04001053#define vec_sort_with_function(vec,f) \
1054do { \
1055 if (vec_len (vec) > 1) \
1056 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -07001057} while (0)
1058
1059/** \brief Make a vector containing a NULL terminated c-string.
1060
Dave Barachc3799992016-08-15 11:12:27 -04001061 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001062 @param S pointer to string buffer.
1063 @param L string length (NOT including the terminating NULL; a la strlen())
1064*/
1065#define vec_validate_init_c_string(V, S, L) \
1066 do { \
1067 vec_reset_length (V); \
1068 vec_validate ((V), (L)); \
1069 if ((S) && (L)) \
Dave Barach178cf492018-11-13 16:34:13 -05001070 clib_memcpy_fast ((V), (S), (L)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -07001071 (V)[(L)] = 0; \
1072 } while (0)
1073
1074
Chris Lukeb5850972016-05-03 16:34:59 -04001075/** \brief Test whether a vector is a NULL terminated c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001076
Dave Barachc3799992016-08-15 11:12:27 -04001077 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001078 @return BOOLEAN indicating if the vector c-string is null terminated.
1079*/
1080#define vec_c_string_is_terminated(V) \
1081 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
1082
Chris Lukeb5850972016-05-03 16:34:59 -04001083/** \brief (If necessary) NULL terminate a vector containing a c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001084
Dave Barachc3799992016-08-15 11:12:27 -04001085 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -07001086 @return V (value-result macro parameter)
1087*/
1088#define vec_terminate_c_string(V) \
1089 do { \
1090 u32 vl = vec_len ((V)); \
1091 if (!vec_c_string_is_terminated(V)) \
1092 { \
1093 vec_validate ((V), vl); \
1094 (V)[vl] = 0; \
1095 } \
1096 } while (0)
1097
1098#endif /* included_vec_h */
1099
Dave Barachc3799992016-08-15 11:12:27 -04001100
1101/*
1102 * fd.io coding-style-patch-verification: ON
1103 *
1104 * Local Variables:
1105 * eval: (c-set-style "gnu")
1106 * End:
1107 */