blob: e2cb24c5ce793f48b260212224e281c641791997 [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
73 Users may specify the alignment for data elements via the
74 vec_*_aligned macros.
75
76 Vectors elements can be any C type e.g. (int, double, struct bar).
77 This is also true for data types built atop vectors (e.g. heap,
78 pool, etc.).
79
80 Many macros have _a variants supporting alignment of vector data
81 and _h variants supporting non zero length vector headers.
82 The _ha variants support both.
83
Dave Barachc3799992016-08-15 11:12:27 -040084 Standard programming error: memorize a pointer to the ith element
Ed Warnickecb9cada2015-12-08 15:45:58 -070085 of a vector then expand it. Vectors expand by 3/2, so such code
86 may appear to work for a period of time. Memorize vector indices
Dave Barachc3799992016-08-15 11:12:27 -040087 which are invariant.
Ed Warnickecb9cada2015-12-08 15:45:58 -070088 */
89
90/** \brief Low-level resize allocation function, usually not called directly
91
92 @param v pointer to a vector
93 @param length_increment length increment in elements
94 @param data_bytes requested size in bytes
95 @param header_bytes header size in bytes (may be zero)
96 @param data_align alignment (may be zero)
97 @return v_prime pointer to resized vector, may or may not equal v
98*/
Dave Barachc3799992016-08-15 11:12:27 -040099void *vec_resize_allocate_memory (void *v,
100 word length_increment,
101 uword data_bytes,
102 uword header_bytes, uword data_align);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103
104/** \brief Low-level vector resize function, usually not called directly
105
106 @param v pointer to a vector
107 @param length_increment length increment in elements
108 @param data_bytes requested size in bytes
109 @param header_bytes header size in bytes (may be zero)
110 @param data_align alignment (may be zero)
111 @return v_prime pointer to resized vector, may or may not equal v
112*/
113
114always_inline void *
Dave Barachc3799992016-08-15 11:12:27 -0400115_vec_resize (void *v,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116 word length_increment,
Dave Barachc3799992016-08-15 11:12:27 -0400117 uword data_bytes, uword header_bytes, uword data_align)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700118{
Dave Barachc3799992016-08-15 11:12:27 -0400119 vec_header_t *vh = _vec_find (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120 uword new_data_bytes, aligned_header_bytes;
121
122 aligned_header_bytes = vec_header_bytes (header_bytes);
123
124 new_data_bytes = data_bytes + aligned_header_bytes;
125
126 if (PREDICT_TRUE (v != 0))
127 {
Dave Barachc3799992016-08-15 11:12:27 -0400128 void *p = v - aligned_header_bytes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129
130 /* Vector header must start heap object. */
131 ASSERT (clib_mem_is_heap_object (p));
132
133 /* Typically we'll not need to resize. */
134 if (new_data_bytes <= clib_mem_size (p))
135 {
136 vh->len += length_increment;
137 return v;
138 }
139 }
140
141 /* Slow path: call helper function. */
Dave Barachc3799992016-08-15 11:12:27 -0400142 return vec_resize_allocate_memory (v, length_increment, data_bytes,
143 header_bytes,
144 clib_max (sizeof (vec_header_t),
145 data_align));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146}
147
Florin Corasef5d5aa2017-11-02 19:28:09 -0400148/** \brief Determine if vector will resize with next allocation
Dave Barach614ac5d2017-02-06 09:28:03 -0500149
150 @param v pointer to a vector
151 @param length_increment length increment in elements
152 @param data_bytes requested size in bytes
153 @param header_bytes header size in bytes (may be zero)
154 @param data_align alignment (may be zero)
Florin Corasef5d5aa2017-11-02 19:28:09 -0400155 @return 1 if vector will resize 0 otherwise
Dave Barach614ac5d2017-02-06 09:28:03 -0500156*/
157
158always_inline int
159_vec_resize_will_expand (void *v,
160 word length_increment,
161 uword data_bytes, uword header_bytes,
162 uword data_align)
163{
Dave Barach614ac5d2017-02-06 09:28:03 -0500164 uword new_data_bytes, aligned_header_bytes;
165
166 aligned_header_bytes = vec_header_bytes (header_bytes);
167
168 new_data_bytes = data_bytes + aligned_header_bytes;
169
170 if (PREDICT_TRUE (v != 0))
171 {
172 void *p = v - aligned_header_bytes;
173
174 /* Vector header must start heap object. */
175 ASSERT (clib_mem_is_heap_object (p));
176
177 /* Typically we'll not need to resize. */
178 if (new_data_bytes <= clib_mem_size (p))
Florin Corasef5d5aa2017-11-02 19:28:09 -0400179 return 0;
Dave Barach614ac5d2017-02-06 09:28:03 -0500180 }
181 return 1;
182}
183
Dave Barachc3799992016-08-15 11:12:27 -0400184/** \brief Predicate function, says whether the supplied vector is a clib heap
185 object (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700186
187 @param v pointer to a vector
188 @param header_bytes vector header size in bytes (may be zero)
189 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400190*/
191uword clib_mem_is_vec_h (void *v, uword header_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700192
193
Dave Barachc3799992016-08-15 11:12:27 -0400194/** \brief Predicate function, says whether the supplied vector is a clib heap
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195 object
196
197 @param v pointer to a vector
198 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400199*/
200always_inline uword
201clib_mem_is_vec (void *v)
202{
203 return clib_mem_is_vec_h (v, 0);
204}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205
206/* Local variable naming macro (prevents collisions with other macro naming). */
207#define _v(var) _vec_##var
208
209/** \brief Resize a vector (general version).
210 Add N elements to end of given vector V, return pointer to start of vector.
211 Vector will have room for H header bytes and will have user's data aligned
212 at alignment A (rounded to next power of 2).
213
214 @param V pointer to a vector
215 @param N number of elements to add
216 @param H header size in bytes (may be zero)
217 @param A alignment (may be zero)
218 @return V (value-result macro parameter)
219*/
220
221#define vec_resize_ha(V,N,H,A) \
222do { \
223 word _v(n) = (N); \
224 word _v(l) = vec_len (V); \
225 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
226} while (0)
227
228/** \brief Resize a vector (no header, unspecified alignment)
229 Add N elements to end of given vector V, return pointer to start of vector.
230 Vector will have room for H header bytes and will have user's data aligned
231 at alignment A (rounded to next power of 2).
232
233 @param V pointer to a vector
234 @param N number of elements to add
235 @return V (value-result macro parameter)
236*/
237#define vec_resize(V,N) vec_resize_ha(V,N,0,0)
238
239/** \brief Resize a vector (no header, alignment specified).
240 Add N elements to end of given vector V, return pointer to start of vector.
241 Vector will have room for H header bytes and will have user's data aligned
242 at alignment A (rounded to next power of 2).
243
244 @param V pointer to a vector
245 @param N number of elements to add
246 @param A alignment (may be zero)
247 @return V (value-result macro parameter)
248*/
249
250#define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
251
Dave Barachc3799992016-08-15 11:12:27 -0400252/** \brief Allocate space for N more elements
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253
254 @param V pointer to a vector
255 @param N number of elements to add
256 @param H header size in bytes (may be zero)
257 @param A alignment (may be zero)
258 @return V (value-result macro parameter)
259*/
260
261#define vec_alloc_ha(V,N,H,A) \
262do { \
263 uword _v(l) = vec_len (V); \
264 vec_resize_ha (V, N, H, A); \
265 _vec_len (V) = _v(l); \
266} while (0)
267
Dave Barachc3799992016-08-15 11:12:27 -0400268/** \brief Allocate space for N more elements
269 (no header, unspecified alignment)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700270
271 @param V pointer to a vector
272 @param N number of elements to add
273 @return V (value-result macro parameter)
274*/
275#define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
276
277/** \brief Allocate space for N more elements (no header, given alignment)
278 @param V pointer to a vector
279 @param N number of elements to add
280 @param A alignment (may be zero)
281 @return V (value-result macro parameter)
282*/
283
284#define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
285
286/** \brief Create new vector of given type and length (general version).
287 @param T type of elements in new vector
288 @param N number of elements to add
289 @param H header size in bytes (may be zero)
290 @param A alignment (may be zero)
291 @return V new vector
292*/
293#define vec_new_ha(T,N,H,A) \
294({ \
295 word _v(n) = (N); \
296 _vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
297})
298
Dave Barachc3799992016-08-15 11:12:27 -0400299/** \brief Create new vector of given type and length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700300 (unspecified alignment, no header).
301
302 @param T type of elements in new vector
303 @param N number of elements to add
304 @return V new vector
305*/
306#define vec_new(T,N) vec_new_ha(T,N,0,0)
Dave Barachc3799992016-08-15 11:12:27 -0400307/** \brief Create new vector of given type and length
308 (alignment specified, no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700309
310 @param T type of elements in new vector
311 @param N number of elements to add
312 @param A alignment (may be zero)
313 @return V new vector
314*/
315#define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
316
317/** \brief Free vector's memory (general version)
318
319 @param V pointer to a vector
320 @param H size of header in bytes
321 @return V (value-result parameter, V=0)
322*/
323#define vec_free_h(V,H) \
324do { \
325 if (V) \
326 { \
327 clib_mem_free (vec_header ((V), (H))); \
328 V = 0; \
329 } \
330} while (0)
331
Dave Barachc3799992016-08-15 11:12:27 -0400332/** \brief Free vector's memory (no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333 @param V pointer to a vector
334 @return V (value-result parameter, V=0)
335*/
336#define vec_free(V) vec_free_h(V,0)
337
338/**\brief Free vector user header (syntactic sugar)
339 @param h vector header
340 @void
341*/
342#define vec_free_header(h) clib_mem_free (h)
343
344/** \brief Return copy of vector (general version).
345
346 @param V pointer to a vector
347 @param H size of header in bytes
348 @param A alignment (may be zero)
349
350 @return Vdup copy of vector
351*/
352
353#define vec_dup_ha(V,H,A) \
354({ \
355 __typeof__ ((V)[0]) * _v(v) = 0; \
356 uword _v(l) = vec_len (V); \
357 if (_v(l) > 0) \
358 { \
359 vec_resize_ha (_v(v), _v(l), (H), (A)); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100360 clib_memcpy (_v(v), (V), _v(l) * sizeof ((V)[0]));\
Ed Warnickecb9cada2015-12-08 15:45:58 -0700361 } \
362 _v(v); \
363})
364
365/** \brief Return copy of vector (no header, no alignment)
366
367 @param V pointer to a vector
368 @return Vdup copy of vector
369*/
370#define vec_dup(V) vec_dup_ha(V,0,0)
371
372/** \brief Return copy of vector (no header, alignment specified).
373
374 @param V pointer to a vector
375 @param A alignment (may be zero)
376
377 @return Vdup copy of vector
378*/
379#define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
380
381/** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
382 sizeof(DST[0])
383
Dave Barachc3799992016-08-15 11:12:27 -0400384 @param DST destination
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385 @param SRC source
386*/
Damjan Marionf1213b82016-03-13 02:22:06 +0100387#define vec_copy(DST,SRC) clib_memcpy (DST, SRC, vec_len (DST) * \
388 sizeof ((DST)[0]))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700389
Dave Barachc3799992016-08-15 11:12:27 -0400390/** \brief Clone a vector. Make a new vector with the
Ed Warnickecb9cada2015-12-08 15:45:58 -0700391 same size as a given vector but possibly with a different type.
392
393 @param NEW_V pointer to new vector
394 @param OLD_V pointer to old vector
395*/
396#define vec_clone(NEW_V,OLD_V) \
397do { \
398 (NEW_V) = 0; \
399 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
400 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
401} while (0)
402
403/** \brief Make sure vector is long enough for given index (general version).
404
Dave Barachc3799992016-08-15 11:12:27 -0400405 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406 @param I vector index which will be valid upon return
407 @param H header size in bytes (may be zero)
408 @param A alignment (may be zero)
409 @return V (value-result macro parameter)
410*/
411
412#define vec_validate_ha(V,I,H,A) \
413do { \
414 word _v(i) = (I); \
415 word _v(l) = vec_len (V); \
416 if (_v(i) >= _v(l)) \
417 { \
418 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
419 /* Must zero new space since user may have previously \
420 used e.g. _vec_len (v) -= 10 */ \
421 memset ((V) + _v(l), 0, (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
422 } \
423} while (0)
424
Dave Barachc3799992016-08-15 11:12:27 -0400425/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700426 (no header, unspecified alignment)
427
Dave Barachc3799992016-08-15 11:12:27 -0400428 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700429 @param I vector index which will be valid upon return
430 @return V (value-result macro parameter)
431*/
432#define vec_validate(V,I) vec_validate_ha(V,I,0,0)
433
Dave Barachc3799992016-08-15 11:12:27 -0400434/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435 (no header, specified alignment)
436
Dave Barachc3799992016-08-15 11:12:27 -0400437 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700438 @param I vector index which will be valid upon return
439 @param A alignment (may be zero)
440 @return V (value-result macro parameter)
441*/
442
443#define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
444
Dave Barachc3799992016-08-15 11:12:27 -0400445/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700446 and initialize empty space (general version)
447
Dave Barachc3799992016-08-15 11:12:27 -0400448 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700449 @param I vector index which will be valid upon return
450 @param INIT initial value (can be a complex expression!)
451 @param H header size in bytes (may be zero)
452 @param A alignment (may be zero)
453 @return V (value-result macro parameter)
454*/
455#define vec_validate_init_empty_ha(V,I,INIT,H,A) \
456do { \
457 word _v(i) = (I); \
458 word _v(l) = vec_len (V); \
459 if (_v(i) >= _v(l)) \
460 { \
461 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
462 while (_v(l) <= _v(i)) \
463 { \
464 (V)[_v(l)] = (INIT); \
465 _v(l)++; \
466 } \
467 } \
468} while (0)
469
Dave Barachc3799992016-08-15 11:12:27 -0400470/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700471 and initialize empty space (no header, unspecified alignment)
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 INIT initial value (can be a complex expression!)
476 @param H header size in bytes (may be zero)
477 @param A alignment (may be zero)
478 @return V (value-result macro parameter)
479*/
480
481#define vec_validate_init_empty(V,I,INIT) \
482 vec_validate_init_empty_ha(V,I,INIT,0,0)
483
Dave Barachc3799992016-08-15 11:12:27 -0400484/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700485 and initialize empty space (no header, alignment alignment)
486
Dave Barachc3799992016-08-15 11:12:27 -0400487 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700488 @param I vector index which will be valid upon return
489 @param INIT initial value (can be a complex expression!)
490 @param H header size in bytes (may be zero)
491 @param A alignment (may be zero)
492 @return V (value-result macro parameter)
493*/
Damjan Marion7d272182017-06-05 21:53:39 +0200494#define vec_validate_init_empty_aligned(V,I,INIT,A) \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700495 vec_validate_init_empty_ha(V,I,INIT,0,A)
496
Dave Barachc3799992016-08-15 11:12:27 -0400497/** \brief Add 1 element to end of vector (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700498
499 @param V pointer to a vector
500 @param E element to add
501 @param H header size in bytes (may be zero)
502 @param A alignment (may be zero)
503 @return V (value-result macro parameter)
504*/
505#define vec_add1_ha(V,E,H,A) \
506do { \
507 word _v(l) = vec_len (V); \
508 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
509 (V)[_v(l)] = (E); \
510} while (0)
511
Dave Barachc3799992016-08-15 11:12:27 -0400512/** \brief Add 1 element to end of vector (unspecified alignment).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513
514 @param V pointer to a vector
515 @param E element to add
516 @return V (value-result macro parameter)
517*/
518#define vec_add1(V,E) vec_add1_ha(V,E,0,0)
519
Dave Barachc3799992016-08-15 11:12:27 -0400520/** \brief Add 1 element to end of vector (alignment specified).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700521
522 @param V pointer to a vector
523 @param E element to add
524 @param H header size in bytes (may be zero)
525 @param A alignment (may be zero)
526 @return V (value-result macro parameter)
527*/
528#define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
529
Dave Barachc3799992016-08-15 11:12:27 -0400530/** \brief Add N elements to end of vector V,
531 return pointer to new elements in P. (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532
533 @param V pointer to a vector
534 @param P pointer to new vector element(s)
535 @param N number of elements to add
536 @param H header size in bytes (may be zero)
537 @param A alignment (may be zero)
538 @return V and P (value-result macro parameters)
539*/
540#define vec_add2_ha(V,P,N,H,A) \
541do { \
542 word _v(n) = (N); \
543 word _v(l) = vec_len (V); \
544 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
545 P = (V) + _v(l); \
546} while (0)
547
Dave Barachc3799992016-08-15 11:12:27 -0400548/** \brief Add N elements to end of vector V,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549 return pointer to new elements in P. (no header, unspecified alignment)
550
551 @param V pointer to a vector
552 @param P pointer to new vector element(s)
553 @param N number of elements to add
554 @return V and P (value-result macro parameters)
555*/
556
557#define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
558
Dave Barachc3799992016-08-15 11:12:27 -0400559/** \brief Add N elements to end of vector V,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700560 return pointer to new elements in P. (no header, alignment specified)
561
562 @param V pointer to a vector
563 @param P pointer to new vector element(s)
564 @param N number of elements to add
565 @param A alignment (may be zero)
566 @return V and P (value-result macro parameters)
567*/
568
569#define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
570
Dave Barachc3799992016-08-15 11:12:27 -0400571/** \brief Add N elements to end of vector V (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700572
573 @param V pointer to a vector
574 @param E pointer to element(s) to add
575 @param N number of elements to add
576 @param H header size in bytes (may be zero)
577 @param A alignment (may be zero)
578 @return V (value-result macro parameter)
579*/
580#define vec_add_ha(V,E,N,H,A) \
581do { \
582 word _v(n) = (N); \
583 word _v(l) = vec_len (V); \
584 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100585 clib_memcpy ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700586} while (0)
587
588/** \brief Add N elements to end of vector V (no header, unspecified alignment)
589
590 @param V pointer to a vector
591 @param E pointer to element(s) to add
592 @param N number of elements to add
593 @return V (value-result macro parameter)
594*/
595#define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
596
597/** \brief Add N elements to end of vector V (no header, specified alignment)
598
599 @param V pointer to a vector
600 @param E pointer to element(s) to add
601 @param N number of elements to add
602 @param A alignment (may be zero)
603 @return V (value-result macro parameter)
604*/
605#define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
606
Dave Barachc3799992016-08-15 11:12:27 -0400607/** \brief Returns last element of a vector and decrements its length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700608
609 @param V pointer to a vector
610 @return E element removed from the end of the vector
611*/
612#define vec_pop(V) \
613({ \
614 uword _v(l) = vec_len (V); \
615 ASSERT (_v(l) > 0); \
616 _v(l) -= 1; \
617 _vec_len (V) = _v (l); \
618 (V)[_v(l)]; \
619})
620
Dave Barachc3799992016-08-15 11:12:27 -0400621/** \brief Set E to the last element of a vector, decrement vector length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700622 @param V pointer to a vector
623 @param E pointer to the last vector element
Dave Barachc3799992016-08-15 11:12:27 -0400624 @return E element removed from the end of the vector
Ed Warnickecb9cada2015-12-08 15:45:58 -0700625 (value-result macro parameter
626*/
627
628#define vec_pop2(V,E) \
629({ \
630 uword _v(l) = vec_len (V); \
631 if (_v(l) > 0) (E) = vec_pop (V); \
632 _v(l) > 0; \
633})
634
Dave Barachc3799992016-08-15 11:12:27 -0400635/** \brief Insert N vector elements starting at element M,
636 initialize new elements (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700637
Dave Barachc3799992016-08-15 11:12:27 -0400638 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639 @param N number of elements to insert
640 @param M insertion point
641 @param INIT initial value (can be a complex expression!)
642 @param H header size in bytes (may be zero)
643 @param A alignment (may be zero)
644 @return V (value-result macro parameter)
645*/
646#define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
647do { \
648 word _v(l) = vec_len (V); \
649 word _v(n) = (N); \
650 word _v(m) = (M); \
651 V = _vec_resize ((V), \
652 _v(n), \
653 (_v(l) + _v(n))*sizeof((V)[0]), \
654 (H), (A)); \
655 ASSERT (_v(m) <= _v(l)); \
656 memmove ((V) + _v(m) + _v(n), \
657 (V) + _v(m), \
658 (_v(l) - _v(m)) * sizeof ((V)[0])); \
659 memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
660} while (0)
661
Dave Barachc3799992016-08-15 11:12:27 -0400662/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700663 initialize new elements to zero (general version)
664
Dave Barachc3799992016-08-15 11:12:27 -0400665 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700666 @param N number of elements to insert
667 @param M insertion point
668 @param H header size in bytes (may be zero)
669 @param A alignment (may be zero)
670 @return V (value-result macro parameter)
671*/
672#define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
673
Dave Barachc3799992016-08-15 11:12:27 -0400674/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700675 initialize new elements to zero (no header, unspecified alignment)
676
Dave Barachc3799992016-08-15 11:12:27 -0400677 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700678 @param N number of elements to insert
679 @param M insertion point
680 @return V (value-result macro parameter)
681*/
682#define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
683
Dave Barachc3799992016-08-15 11:12:27 -0400684/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700685 initialize new elements to zero (no header, alignment specified)
686
Dave Barachc3799992016-08-15 11:12:27 -0400687 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700688 @param N number of elements to insert
689 @param M insertion point
690 @param A alignment (may be zero)
691 @return V (value-result macro parameter)
692*/
693#define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
694
Dave Barachc3799992016-08-15 11:12:27 -0400695/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696 initialize new elements (no header, unspecified alignment)
697
Dave Barachc3799992016-08-15 11:12:27 -0400698 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700699 @param N number of elements to insert
700 @param M insertion point
701 @param INIT initial value (can be a complex expression!)
702 @return V (value-result macro parameter)
703*/
704
705#define vec_insert_init_empty(V,N,M,INIT) \
706 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
707/* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
708
Dave Barachc3799992016-08-15 11:12:27 -0400709/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700710 initialize new elements (no header, specified alignment)
711
Dave Barachc3799992016-08-15 11:12:27 -0400712 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713 @param N number of elements to insert
714 @param M insertion point
715 @param INIT initial value (can be a complex expression!)
716 @param A alignment (may be zero)
717 @return V (value-result macro parameter)
718*/
719#define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
720 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
721
Dave Barachc3799992016-08-15 11:12:27 -0400722/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700723 insert given elements (general version)
724
Dave Barachc3799992016-08-15 11:12:27 -0400725 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700726 @param E element(s) to insert
727 @param N number of elements to insert
728 @param M insertion point
729 @param H header size in bytes (may be zero)
730 @param A alignment (may be zero)
731 @return V (value-result macro parameter)
732*/
733
734#define vec_insert_elts_ha(V,E,N,M,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])); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100747 clib_memcpy ((V) + _v(m), (E), \
748 _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700749} while (0)
750
Dave Barachc3799992016-08-15 11:12:27 -0400751/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700752 insert given elements (no header, unspecified alignment)
753
Dave Barachc3799992016-08-15 11:12:27 -0400754 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700755 @param E element(s) to insert
756 @param N number of elements to insert
757 @param M insertion point
758 @return V (value-result macro parameter)
759*/
760#define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
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 insert given elements (no header, specified 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 E element(s) to insert
767 @param N number of elements to insert
768 @param M insertion point
769 @param A alignment (may be zero)
770 @return V (value-result macro parameter)
771*/
772#define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
773
Dave Barachc3799992016-08-15 11:12:27 -0400774/** \brief Delete N elements starting at element M
Ed Warnickecb9cada2015-12-08 15:45:58 -0700775
776 @param V pointer to a vector
777 @param N number of elements to delete
778 @param M first element to delete
779 @return V (value-result macro parameter)
780*/
781#define vec_delete(V,N,M) \
782do { \
783 word _v(l) = vec_len (V); \
784 word _v(n) = (N); \
785 word _v(m) = (M); \
786 /* Copy over deleted elements. */ \
787 if (_v(l) - _v(n) - _v(m) > 0) \
788 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
789 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
790 /* Zero empty space at end (for future re-allocation). */ \
791 if (_v(n) > 0) \
792 memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
793 _vec_len (V) -= _v(n); \
794} while (0)
795
796/** \brief Delete the element at index I
797
798 @param V pointer to a vector
799 @param I index to delete
800*/
801#define vec_del1(v,i) \
802do { \
803 uword _vec_del_l = _vec_len (v) - 1; \
804 uword _vec_del_i = (i); \
805 if (_vec_del_i < _vec_del_l) \
806 (v)[_vec_del_i] = (v)[_vec_del_l]; \
807 _vec_len (v) = _vec_del_l; \
808} while (0)
809
810/** \brief Append v2 after v1. Result in v1.
811 @param V1 target vector
812 @param V2 vector to append
813*/
Dave Barachc3799992016-08-15 11:12:27 -0400814
Ed Warnickecb9cada2015-12-08 15:45:58 -0700815#define vec_append(v1,v2) \
816do { \
817 uword _v(l1) = vec_len (v1); \
818 uword _v(l2) = vec_len (v2); \
819 \
820 v1 = _vec_resize ((v1), _v(l2), \
821 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100822 clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700823} while (0)
824
825/** \brief Append v2 after v1. Result in v1. Specified alignment.
826 @param V1 target vector
827 @param V2 vector to append
828 @param align required alignment
829*/
Dave Barachc3799992016-08-15 11:12:27 -0400830
Ed Warnickecb9cada2015-12-08 15:45:58 -0700831#define vec_append_aligned(v1,v2,align) \
832do { \
833 uword _v(l1) = vec_len (v1); \
834 uword _v(l2) = vec_len (v2); \
835 \
836 v1 = _vec_resize ((v1), _v(l2), \
837 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100838 clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700839} while (0)
840
841/** \brief Prepend v2 before v1. Result in v1.
842 @param V1 target vector
843 @param V2 vector to prepend
844*/
845
846#define vec_prepend(v1,v2) \
847do { \
848 uword _v(l1) = vec_len (v1); \
849 uword _v(l2) = vec_len (v2); \
850 \
851 v1 = _vec_resize ((v1), _v(l2), \
852 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
853 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100854 clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700855} while (0)
856
857/** \brief Prepend v2 before v1. Result in v1. Specified alignment
858 @param V1 target vector
859 @param V2 vector to prepend
860 @param align required alignment
861*/
862
863#define vec_prepend_aligned(v1,v2,align) \
864do { \
865 uword _v(l1) = vec_len (v1); \
866 uword _v(l2) = vec_len (v2); \
867 \
868 v1 = _vec_resize ((v1), _v(l2), \
869 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
870 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100871 clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700872} while (0)
873
874
875/** \brief Zero all vector elements. Null-pointer tolerant.
876 @param var Vector to zero
877*/
878#define vec_zero(var) \
879do { \
880 if (var) \
881 memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
882} while (0)
883
884/** \brief Set all vector elements to given value. Null-pointer tolerant.
885 @param v vector to set
886 @param val value for each vector element
887*/
888#define vec_set(v,val) \
889do { \
890 word _v(i); \
891 __typeof__ ((v)[0]) _val = (val); \
892 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
893 (v)[_v(i)] = _val; \
894} while (0)
895
896#ifdef CLIB_UNIX
897#include <stdlib.h> /* for qsort */
898#endif
899
900/** \brief Compare two vectors, not NULL-pointer tolerant
901
902 @param v1 Pointer to a vector
903 @param v2 Pointer to a vector
904 @return 1 if equal, 0 if unequal
905*/
906#define vec_is_equal(v1,v2) \
907 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
908
909/** \brief Compare two vectors (only applicable to vectors of signed numbers).
Dave Barachc3799992016-08-15 11:12:27 -0400910 Used in qsort compare functions.
911
Ed Warnickecb9cada2015-12-08 15:45:58 -0700912 @param v1 Pointer to a vector
913 @param v2 Pointer to a vector
914 @return -1, 0, +1
915*/
916#define vec_cmp(v1,v2) \
917({ \
918 word _v(i), _v(cmp), _v(l); \
919 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
920 _v(cmp) = 0; \
921 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
922 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
923 if (_v(cmp)) \
924 break; \
925 } \
926 if (_v(cmp) == 0 && _v(l) > 0) \
927 _v(cmp) = vec_len(v1) - vec_len(v2); \
928 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
929})
930
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100931/** \brief Search a vector for the index of the entry that matches.
932
933 @param v1 Pointer to a vector
934 @param v2 Entry to match
935 @return index of match or ~0
936*/
937#define vec_search(v,E) \
938({ \
939 word _v(i) = 0; \
940 while (_v(i) < vec_len(v)) \
941 { \
Andrew Yourtchenkof908a032017-06-20 12:26:23 +0200942 if ((v)[_v(i)] == E) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100943 break; \
944 _v(i)++; \
945 } \
946 if (_v(i) == vec_len(v)) \
947 _v(i) = ~0; \
948 _v(i); \
949})
950
Ed Warnickecb9cada2015-12-08 15:45:58 -0700951/** \brief Sort a vector using the supplied element comparison function
952
953 @param vec vector to sort
954 @param f comparison function
955*/
956#define vec_sort_with_function(vec,f) \
957do { \
958 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
959} while (0)
960
961/** \brief Make a vector containing a NULL terminated c-string.
962
Dave Barachc3799992016-08-15 11:12:27 -0400963 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700964 @param S pointer to string buffer.
965 @param L string length (NOT including the terminating NULL; a la strlen())
966*/
967#define vec_validate_init_c_string(V, S, L) \
968 do { \
969 vec_reset_length (V); \
970 vec_validate ((V), (L)); \
971 if ((S) && (L)) \
Damjan Marionf1213b82016-03-13 02:22:06 +0100972 clib_memcpy ((V), (S), (L)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700973 (V)[(L)] = 0; \
974 } while (0)
975
976
Chris Lukeb5850972016-05-03 16:34:59 -0400977/** \brief Test whether a vector is a NULL terminated c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700978
Dave Barachc3799992016-08-15 11:12:27 -0400979 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700980 @return BOOLEAN indicating if the vector c-string is null terminated.
981*/
982#define vec_c_string_is_terminated(V) \
983 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
984
Chris Lukeb5850972016-05-03 16:34:59 -0400985/** \brief (If necessary) NULL terminate a vector containing a c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700986
Dave Barachc3799992016-08-15 11:12:27 -0400987 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700988 @return V (value-result macro parameter)
989*/
990#define vec_terminate_c_string(V) \
991 do { \
992 u32 vl = vec_len ((V)); \
993 if (!vec_c_string_is_terminated(V)) \
994 { \
995 vec_validate ((V), vl); \
996 (V)[vl] = 0; \
997 } \
998 } while (0)
999
1000#endif /* included_vec_h */
1001
Dave Barachc3799992016-08-15 11:12:27 -04001002
1003/*
1004 * fd.io coding-style-patch-verification: ON
1005 *
1006 * Local Variables:
1007 * eval: (c-set-style "gnu")
1008 * End:
1009 */