blob: eed96d6b9c2608aac25f97e77293e8a866148769 [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
Dave Barachc3799992016-08-15 11:12:27 -0400148/** \brief Predicate function, says whether the supplied vector is a clib heap
149 object (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150
151 @param v pointer to a vector
152 @param header_bytes vector header size in bytes (may be zero)
153 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400154*/
155uword clib_mem_is_vec_h (void *v, uword header_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700156
157
Dave Barachc3799992016-08-15 11:12:27 -0400158/** \brief Predicate function, says whether the supplied vector is a clib heap
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159 object
160
161 @param v pointer to a vector
162 @return 0 or 1
Dave Barachc3799992016-08-15 11:12:27 -0400163*/
164always_inline uword
165clib_mem_is_vec (void *v)
166{
167 return clib_mem_is_vec_h (v, 0);
168}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169
170/* Local variable naming macro (prevents collisions with other macro naming). */
171#define _v(var) _vec_##var
172
173/** \brief Resize a vector (general version).
174 Add N elements to end of given vector V, return pointer to start of vector.
175 Vector will have room for H header bytes and will have user's data aligned
176 at alignment A (rounded to next power of 2).
177
178 @param V pointer to a vector
179 @param N number of elements to add
180 @param H header size in bytes (may be zero)
181 @param A alignment (may be zero)
182 @return V (value-result macro parameter)
183*/
184
185#define vec_resize_ha(V,N,H,A) \
186do { \
187 word _v(n) = (N); \
188 word _v(l) = vec_len (V); \
189 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
190} while (0)
191
192/** \brief Resize a vector (no header, unspecified alignment)
193 Add N elements to end of given vector V, return pointer to start of vector.
194 Vector will have room for H header bytes and will have user's data aligned
195 at alignment A (rounded to next power of 2).
196
197 @param V pointer to a vector
198 @param N number of elements to add
199 @return V (value-result macro parameter)
200*/
201#define vec_resize(V,N) vec_resize_ha(V,N,0,0)
202
203/** \brief Resize a vector (no header, alignment specified).
204 Add N elements to end of given vector V, return pointer to start of vector.
205 Vector will have room for H header bytes and will have user's data aligned
206 at alignment A (rounded to next power of 2).
207
208 @param V pointer to a vector
209 @param N number of elements to add
210 @param A alignment (may be zero)
211 @return V (value-result macro parameter)
212*/
213
214#define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
215
Dave Barachc3799992016-08-15 11:12:27 -0400216/** \brief Allocate space for N more elements
Ed Warnickecb9cada2015-12-08 15:45:58 -0700217
218 @param V pointer to a vector
219 @param N number of elements to add
220 @param H header size in bytes (may be zero)
221 @param A alignment (may be zero)
222 @return V (value-result macro parameter)
223*/
224
225#define vec_alloc_ha(V,N,H,A) \
226do { \
227 uword _v(l) = vec_len (V); \
228 vec_resize_ha (V, N, H, A); \
229 _vec_len (V) = _v(l); \
230} while (0)
231
Dave Barachc3799992016-08-15 11:12:27 -0400232/** \brief Allocate space for N more elements
233 (no header, unspecified alignment)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700234
235 @param V pointer to a vector
236 @param N number of elements to add
237 @return V (value-result macro parameter)
238*/
239#define vec_alloc(V,N) vec_alloc_ha(V,N,0,0)
240
241/** \brief Allocate space for N more elements (no header, given alignment)
242 @param V pointer to a vector
243 @param N number of elements to add
244 @param A alignment (may be zero)
245 @return V (value-result macro parameter)
246*/
247
248#define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
249
250/** \brief Create new vector of given type and length (general version).
251 @param T type of elements in new vector
252 @param N number of elements to add
253 @param H header size in bytes (may be zero)
254 @param A alignment (may be zero)
255 @return V new vector
256*/
257#define vec_new_ha(T,N,H,A) \
258({ \
259 word _v(n) = (N); \
260 _vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
261})
262
Dave Barachc3799992016-08-15 11:12:27 -0400263/** \brief Create new vector of given type and length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264 (unspecified alignment, no header).
265
266 @param T type of elements in new vector
267 @param N number of elements to add
268 @return V new vector
269*/
270#define vec_new(T,N) vec_new_ha(T,N,0,0)
Dave Barachc3799992016-08-15 11:12:27 -0400271/** \brief Create new vector of given type and length
272 (alignment specified, no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700273
274 @param T type of elements in new vector
275 @param N number of elements to add
276 @param A alignment (may be zero)
277 @return V new vector
278*/
279#define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
280
281/** \brief Free vector's memory (general version)
282
283 @param V pointer to a vector
284 @param H size of header in bytes
285 @return V (value-result parameter, V=0)
286*/
287#define vec_free_h(V,H) \
288do { \
289 if (V) \
290 { \
291 clib_mem_free (vec_header ((V), (H))); \
292 V = 0; \
293 } \
294} while (0)
295
Dave Barachc3799992016-08-15 11:12:27 -0400296/** \brief Free vector's memory (no header).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297 @param V pointer to a vector
298 @return V (value-result parameter, V=0)
299*/
300#define vec_free(V) vec_free_h(V,0)
301
302/**\brief Free vector user header (syntactic sugar)
303 @param h vector header
304 @void
305*/
306#define vec_free_header(h) clib_mem_free (h)
307
308/** \brief Return copy of vector (general version).
309
310 @param V pointer to a vector
311 @param H size of header in bytes
312 @param A alignment (may be zero)
313
314 @return Vdup copy of vector
315*/
316
317#define vec_dup_ha(V,H,A) \
318({ \
319 __typeof__ ((V)[0]) * _v(v) = 0; \
320 uword _v(l) = vec_len (V); \
321 if (_v(l) > 0) \
322 { \
323 vec_resize_ha (_v(v), _v(l), (H), (A)); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100324 clib_memcpy (_v(v), (V), _v(l) * sizeof ((V)[0]));\
Ed Warnickecb9cada2015-12-08 15:45:58 -0700325 } \
326 _v(v); \
327})
328
329/** \brief Return copy of vector (no header, no alignment)
330
331 @param V pointer to a vector
332 @return Vdup copy of vector
333*/
334#define vec_dup(V) vec_dup_ha(V,0,0)
335
336/** \brief Return copy of vector (no header, alignment specified).
337
338 @param V pointer to a vector
339 @param A alignment (may be zero)
340
341 @return Vdup copy of vector
342*/
343#define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
344
345/** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
346 sizeof(DST[0])
347
Dave Barachc3799992016-08-15 11:12:27 -0400348 @param DST destination
Ed Warnickecb9cada2015-12-08 15:45:58 -0700349 @param SRC source
350*/
Damjan Marionf1213b82016-03-13 02:22:06 +0100351#define vec_copy(DST,SRC) clib_memcpy (DST, SRC, vec_len (DST) * \
352 sizeof ((DST)[0]))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353
Dave Barachc3799992016-08-15 11:12:27 -0400354/** \brief Clone a vector. Make a new vector with the
Ed Warnickecb9cada2015-12-08 15:45:58 -0700355 same size as a given vector but possibly with a different type.
356
357 @param NEW_V pointer to new vector
358 @param OLD_V pointer to old vector
359*/
360#define vec_clone(NEW_V,OLD_V) \
361do { \
362 (NEW_V) = 0; \
363 (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
364 vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
365} while (0)
366
367/** \brief Make sure vector is long enough for given index (general version).
368
Dave Barachc3799992016-08-15 11:12:27 -0400369 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700370 @param I vector index which will be valid upon return
371 @param H header size in bytes (may be zero)
372 @param A alignment (may be zero)
373 @return V (value-result macro parameter)
374*/
375
376#define vec_validate_ha(V,I,H,A) \
377do { \
378 word _v(i) = (I); \
379 word _v(l) = vec_len (V); \
380 if (_v(i) >= _v(l)) \
381 { \
382 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
383 /* Must zero new space since user may have previously \
384 used e.g. _vec_len (v) -= 10 */ \
385 memset ((V) + _v(l), 0, (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
386 } \
387} while (0)
388
Dave Barachc3799992016-08-15 11:12:27 -0400389/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390 (no header, unspecified alignment)
391
Dave Barachc3799992016-08-15 11:12:27 -0400392 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700393 @param I vector index which will be valid upon return
394 @return V (value-result macro parameter)
395*/
396#define vec_validate(V,I) vec_validate_ha(V,I,0,0)
397
Dave Barachc3799992016-08-15 11:12:27 -0400398/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399 (no header, specified alignment)
400
Dave Barachc3799992016-08-15 11:12:27 -0400401 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402 @param I vector index which will be valid upon return
403 @param A alignment (may be zero)
404 @return V (value-result macro parameter)
405*/
406
407#define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
408
Dave Barachc3799992016-08-15 11:12:27 -0400409/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700410 and initialize empty space (general version)
411
Dave Barachc3799992016-08-15 11:12:27 -0400412 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700413 @param I vector index which will be valid upon return
414 @param INIT initial value (can be a complex expression!)
415 @param H header size in bytes (may be zero)
416 @param A alignment (may be zero)
417 @return V (value-result macro parameter)
418*/
419#define vec_validate_init_empty_ha(V,I,INIT,H,A) \
420do { \
421 word _v(i) = (I); \
422 word _v(l) = vec_len (V); \
423 if (_v(i) >= _v(l)) \
424 { \
425 vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
426 while (_v(l) <= _v(i)) \
427 { \
428 (V)[_v(l)] = (INIT); \
429 _v(l)++; \
430 } \
431 } \
432} while (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 and initialize empty space (no header, unspecified 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 INIT initial value (can be a complex expression!)
440 @param H header size in bytes (may be zero)
441 @param A alignment (may be zero)
442 @return V (value-result macro parameter)
443*/
444
445#define vec_validate_init_empty(V,I,INIT) \
446 vec_validate_init_empty_ha(V,I,INIT,0,0)
447
Dave Barachc3799992016-08-15 11:12:27 -0400448/** \brief Make sure vector is long enough for given index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700449 and initialize empty space (no header, alignment alignment)
450
Dave Barachc3799992016-08-15 11:12:27 -0400451 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700452 @param I vector index which will be valid upon return
453 @param INIT initial value (can be a complex expression!)
454 @param H header size in bytes (may be zero)
455 @param A alignment (may be zero)
456 @return V (value-result macro parameter)
457*/
458#define vec_validate_init_empty_aligned(V,I,A) \
459 vec_validate_init_empty_ha(V,I,INIT,0,A)
460
Dave Barachc3799992016-08-15 11:12:27 -0400461/** \brief Add 1 element to end of vector (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700462
463 @param V pointer to a vector
464 @param E element to add
465 @param H header size in bytes (may be zero)
466 @param A alignment (may be zero)
467 @return V (value-result macro parameter)
468*/
469#define vec_add1_ha(V,E,H,A) \
470do { \
471 word _v(l) = vec_len (V); \
472 V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
473 (V)[_v(l)] = (E); \
474} while (0)
475
Dave Barachc3799992016-08-15 11:12:27 -0400476/** \brief Add 1 element to end of vector (unspecified alignment).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700477
478 @param V pointer to a vector
479 @param E element to add
480 @return V (value-result macro parameter)
481*/
482#define vec_add1(V,E) vec_add1_ha(V,E,0,0)
483
Dave Barachc3799992016-08-15 11:12:27 -0400484/** \brief Add 1 element to end of vector (alignment specified).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700485
486 @param V pointer to a vector
487 @param E element to add
488 @param H header size in bytes (may be zero)
489 @param A alignment (may be zero)
490 @return V (value-result macro parameter)
491*/
492#define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
493
Dave Barachc3799992016-08-15 11:12:27 -0400494/** \brief Add N elements to end of vector V,
495 return pointer to new elements in P. (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700496
497 @param V pointer to a vector
498 @param P pointer to new vector element(s)
499 @param N number of elements to add
500 @param H header size in bytes (may be zero)
501 @param A alignment (may be zero)
502 @return V and P (value-result macro parameters)
503*/
504#define vec_add2_ha(V,P,N,H,A) \
505do { \
506 word _v(n) = (N); \
507 word _v(l) = vec_len (V); \
508 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
509 P = (V) + _v(l); \
510} while (0)
511
Dave Barachc3799992016-08-15 11:12:27 -0400512/** \brief Add N elements to end of vector V,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513 return pointer to new elements in P. (no header, unspecified alignment)
514
515 @param V pointer to a vector
516 @param P pointer to new vector element(s)
517 @param N number of elements to add
518 @return V and P (value-result macro parameters)
519*/
520
521#define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
522
Dave Barachc3799992016-08-15 11:12:27 -0400523/** \brief Add N elements to end of vector V,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700524 return pointer to new elements in P. (no header, alignment specified)
525
526 @param V pointer to a vector
527 @param P pointer to new vector element(s)
528 @param N number of elements to add
529 @param A alignment (may be zero)
530 @return V and P (value-result macro parameters)
531*/
532
533#define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
534
Dave Barachc3799992016-08-15 11:12:27 -0400535/** \brief Add N elements to end of vector V (general version)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700536
537 @param V pointer to a vector
538 @param E pointer to element(s) to add
539 @param N number of elements to add
540 @param H header size in bytes (may be zero)
541 @param A alignment (may be zero)
542 @return V (value-result macro parameter)
543*/
544#define vec_add_ha(V,E,N,H,A) \
545do { \
546 word _v(n) = (N); \
547 word _v(l) = vec_len (V); \
548 V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100549 clib_memcpy ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700550} while (0)
551
552/** \brief Add N elements to end of vector V (no header, unspecified alignment)
553
554 @param V pointer to a vector
555 @param E pointer to element(s) to add
556 @param N number of elements to add
557 @return V (value-result macro parameter)
558*/
559#define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
560
561/** \brief Add N elements to end of vector V (no header, specified alignment)
562
563 @param V pointer to a vector
564 @param E pointer to element(s) to add
565 @param N number of elements to add
566 @param A alignment (may be zero)
567 @return V (value-result macro parameter)
568*/
569#define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
570
Dave Barachc3799992016-08-15 11:12:27 -0400571/** \brief Returns last element of a vector and decrements its length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700572
573 @param V pointer to a vector
574 @return E element removed from the end of the vector
575*/
576#define vec_pop(V) \
577({ \
578 uword _v(l) = vec_len (V); \
579 ASSERT (_v(l) > 0); \
580 _v(l) -= 1; \
581 _vec_len (V) = _v (l); \
582 (V)[_v(l)]; \
583})
584
Dave Barachc3799992016-08-15 11:12:27 -0400585/** \brief Set E to the last element of a vector, decrement vector length
Ed Warnickecb9cada2015-12-08 15:45:58 -0700586 @param V pointer to a vector
587 @param E pointer to the last vector element
Dave Barachc3799992016-08-15 11:12:27 -0400588 @return E element removed from the end of the vector
Ed Warnickecb9cada2015-12-08 15:45:58 -0700589 (value-result macro parameter
590*/
591
592#define vec_pop2(V,E) \
593({ \
594 uword _v(l) = vec_len (V); \
595 if (_v(l) > 0) (E) = vec_pop (V); \
596 _v(l) > 0; \
597})
598
Dave Barachc3799992016-08-15 11:12:27 -0400599/** \brief Insert N vector elements starting at element M,
600 initialize new elements (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601
Dave Barachc3799992016-08-15 11:12:27 -0400602 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700603 @param N number of elements to insert
604 @param M insertion point
605 @param INIT initial value (can be a complex expression!)
606 @param H header size in bytes (may be zero)
607 @param A alignment (may be zero)
608 @return V (value-result macro parameter)
609*/
610#define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
611do { \
612 word _v(l) = vec_len (V); \
613 word _v(n) = (N); \
614 word _v(m) = (M); \
615 V = _vec_resize ((V), \
616 _v(n), \
617 (_v(l) + _v(n))*sizeof((V)[0]), \
618 (H), (A)); \
619 ASSERT (_v(m) <= _v(l)); \
620 memmove ((V) + _v(m) + _v(n), \
621 (V) + _v(m), \
622 (_v(l) - _v(m)) * sizeof ((V)[0])); \
623 memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
624} while (0)
625
Dave Barachc3799992016-08-15 11:12:27 -0400626/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700627 initialize new elements to zero (general version)
628
Dave Barachc3799992016-08-15 11:12:27 -0400629 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700630 @param N number of elements to insert
631 @param M insertion point
632 @param H header size in bytes (may be zero)
633 @param A alignment (may be zero)
634 @return V (value-result macro parameter)
635*/
636#define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
637
Dave Barachc3799992016-08-15 11:12:27 -0400638/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639 initialize new elements to zero (no header, unspecified alignment)
640
Dave Barachc3799992016-08-15 11:12:27 -0400641 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700642 @param N number of elements to insert
643 @param M insertion point
644 @return V (value-result macro parameter)
645*/
646#define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
647
Dave Barachc3799992016-08-15 11:12:27 -0400648/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700649 initialize new elements to zero (no header, alignment specified)
650
Dave Barachc3799992016-08-15 11:12:27 -0400651 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700652 @param N number of elements to insert
653 @param M insertion point
654 @param A alignment (may be zero)
655 @return V (value-result macro parameter)
656*/
657#define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
658
Dave Barachc3799992016-08-15 11:12:27 -0400659/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660 initialize new elements (no header, unspecified alignment)
661
Dave Barachc3799992016-08-15 11:12:27 -0400662 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700663 @param N number of elements to insert
664 @param M insertion point
665 @param INIT initial value (can be a complex expression!)
666 @return V (value-result macro parameter)
667*/
668
669#define vec_insert_init_empty(V,N,M,INIT) \
670 vec_insert_init_empty_ha(V,N,M,INIT,0,0)
671/* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
672
Dave Barachc3799992016-08-15 11:12:27 -0400673/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674 initialize new elements (no header, specified alignment)
675
Dave Barachc3799992016-08-15 11:12:27 -0400676 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677 @param N number of elements to insert
678 @param M insertion point
679 @param INIT initial value (can be a complex expression!)
680 @param A alignment (may be zero)
681 @return V (value-result macro parameter)
682*/
683#define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
684 vec_insert_init_empty_ha(V,N,M,INIT,0,A)
685
Dave Barachc3799992016-08-15 11:12:27 -0400686/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700687 insert given elements (general version)
688
Dave Barachc3799992016-08-15 11:12:27 -0400689 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700690 @param E element(s) to insert
691 @param N number of elements to insert
692 @param M insertion point
693 @param H header size in bytes (may be zero)
694 @param A alignment (may be zero)
695 @return V (value-result macro parameter)
696*/
697
698#define vec_insert_elts_ha(V,E,N,M,H,A) \
699do { \
700 word _v(l) = vec_len (V); \
701 word _v(n) = (N); \
702 word _v(m) = (M); \
703 V = _vec_resize ((V), \
704 _v(n), \
705 (_v(l) + _v(n))*sizeof((V)[0]), \
706 (H), (A)); \
707 ASSERT (_v(m) <= _v(l)); \
708 memmove ((V) + _v(m) + _v(n), \
709 (V) + _v(m), \
710 (_v(l) - _v(m)) * sizeof ((V)[0])); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100711 clib_memcpy ((V) + _v(m), (E), \
712 _v(n) * sizeof ((V)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713} while (0)
714
Dave Barachc3799992016-08-15 11:12:27 -0400715/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716 insert given elements (no header, unspecified alignment)
717
Dave Barachc3799992016-08-15 11:12:27 -0400718 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700719 @param E element(s) to insert
720 @param N number of elements to insert
721 @param M insertion point
722 @return V (value-result macro parameter)
723*/
724#define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
725
Dave Barachc3799992016-08-15 11:12:27 -0400726/** \brief Insert N vector elements starting at element M,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727 insert given elements (no header, specified alignment)
728
Dave Barachc3799992016-08-15 11:12:27 -0400729 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700730 @param E element(s) to insert
731 @param N number of elements to insert
732 @param M insertion point
733 @param A alignment (may be zero)
734 @return V (value-result macro parameter)
735*/
736#define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
737
Dave Barachc3799992016-08-15 11:12:27 -0400738/** \brief Delete N elements starting at element M
Ed Warnickecb9cada2015-12-08 15:45:58 -0700739
740 @param V pointer to a vector
741 @param N number of elements to delete
742 @param M first element to delete
743 @return V (value-result macro parameter)
744*/
745#define vec_delete(V,N,M) \
746do { \
747 word _v(l) = vec_len (V); \
748 word _v(n) = (N); \
749 word _v(m) = (M); \
750 /* Copy over deleted elements. */ \
751 if (_v(l) - _v(n) - _v(m) > 0) \
752 memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
753 (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
754 /* Zero empty space at end (for future re-allocation). */ \
755 if (_v(n) > 0) \
756 memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
757 _vec_len (V) -= _v(n); \
758} while (0)
759
760/** \brief Delete the element at index I
761
762 @param V pointer to a vector
763 @param I index to delete
764*/
765#define vec_del1(v,i) \
766do { \
767 uword _vec_del_l = _vec_len (v) - 1; \
768 uword _vec_del_i = (i); \
769 if (_vec_del_i < _vec_del_l) \
770 (v)[_vec_del_i] = (v)[_vec_del_l]; \
771 _vec_len (v) = _vec_del_l; \
772} while (0)
773
774/** \brief Append v2 after v1. Result in v1.
775 @param V1 target vector
776 @param V2 vector to append
777*/
Dave Barachc3799992016-08-15 11:12:27 -0400778
Ed Warnickecb9cada2015-12-08 15:45:58 -0700779#define vec_append(v1,v2) \
780do { \
781 uword _v(l1) = vec_len (v1); \
782 uword _v(l2) = vec_len (v2); \
783 \
784 v1 = _vec_resize ((v1), _v(l2), \
785 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100786 clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787} while (0)
788
789/** \brief Append v2 after v1. Result in v1. Specified alignment.
790 @param V1 target vector
791 @param V2 vector to append
792 @param align required alignment
793*/
Dave Barachc3799992016-08-15 11:12:27 -0400794
Ed Warnickecb9cada2015-12-08 15:45:58 -0700795#define vec_append_aligned(v1,v2,align) \
796do { \
797 uword _v(l1) = vec_len (v1); \
798 uword _v(l2) = vec_len (v2); \
799 \
800 v1 = _vec_resize ((v1), _v(l2), \
801 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100802 clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700803} while (0)
804
805/** \brief Prepend v2 before v1. Result in v1.
806 @param V1 target vector
807 @param V2 vector to prepend
808*/
809
810#define vec_prepend(v1,v2) \
811do { \
812 uword _v(l1) = vec_len (v1); \
813 uword _v(l2) = vec_len (v2); \
814 \
815 v1 = _vec_resize ((v1), _v(l2), \
816 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
817 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100818 clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700819} while (0)
820
821/** \brief Prepend v2 before v1. Result in v1. Specified alignment
822 @param V1 target vector
823 @param V2 vector to prepend
824 @param align required alignment
825*/
826
827#define vec_prepend_aligned(v1,v2,align) \
828do { \
829 uword _v(l1) = vec_len (v1); \
830 uword _v(l2) = vec_len (v2); \
831 \
832 v1 = _vec_resize ((v1), _v(l2), \
833 (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
834 memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
Damjan Marionf1213b82016-03-13 02:22:06 +0100835 clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700836} while (0)
837
838
839/** \brief Zero all vector elements. Null-pointer tolerant.
840 @param var Vector to zero
841*/
842#define vec_zero(var) \
843do { \
844 if (var) \
845 memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
846} while (0)
847
848/** \brief Set all vector elements to given value. Null-pointer tolerant.
849 @param v vector to set
850 @param val value for each vector element
851*/
852#define vec_set(v,val) \
853do { \
854 word _v(i); \
855 __typeof__ ((v)[0]) _val = (val); \
856 for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
857 (v)[_v(i)] = _val; \
858} while (0)
859
860#ifdef CLIB_UNIX
861#include <stdlib.h> /* for qsort */
862#endif
863
864/** \brief Compare two vectors, not NULL-pointer tolerant
865
866 @param v1 Pointer to a vector
867 @param v2 Pointer to a vector
868 @return 1 if equal, 0 if unequal
869*/
870#define vec_is_equal(v1,v2) \
871 (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
872
873/** \brief Compare two vectors (only applicable to vectors of signed numbers).
Dave Barachc3799992016-08-15 11:12:27 -0400874 Used in qsort compare functions.
875
Ed Warnickecb9cada2015-12-08 15:45:58 -0700876 @param v1 Pointer to a vector
877 @param v2 Pointer to a vector
878 @return -1, 0, +1
879*/
880#define vec_cmp(v1,v2) \
881({ \
882 word _v(i), _v(cmp), _v(l); \
883 _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
884 _v(cmp) = 0; \
885 for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
886 _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
887 if (_v(cmp)) \
888 break; \
889 } \
890 if (_v(cmp) == 0 && _v(l) > 0) \
891 _v(cmp) = vec_len(v1) - vec_len(v2); \
892 (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
893})
894
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100895/** \brief Search a vector for the index of the entry that matches.
896
897 @param v1 Pointer to a vector
898 @param v2 Entry to match
899 @return index of match or ~0
900*/
901#define vec_search(v,E) \
902({ \
903 word _v(i) = 0; \
904 while (_v(i) < vec_len(v)) \
905 { \
906 if (v[_v(i)] == E) \
907 break; \
908 _v(i)++; \
909 } \
910 if (_v(i) == vec_len(v)) \
911 _v(i) = ~0; \
912 _v(i); \
913})
914
Ed Warnickecb9cada2015-12-08 15:45:58 -0700915/** \brief Sort a vector using the supplied element comparison function
916
917 @param vec vector to sort
918 @param f comparison function
919*/
920#define vec_sort_with_function(vec,f) \
921do { \
922 qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
923} while (0)
924
925/** \brief Make a vector containing a NULL terminated c-string.
926
Dave Barachc3799992016-08-15 11:12:27 -0400927 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700928 @param S pointer to string buffer.
929 @param L string length (NOT including the terminating NULL; a la strlen())
930*/
931#define vec_validate_init_c_string(V, S, L) \
932 do { \
933 vec_reset_length (V); \
934 vec_validate ((V), (L)); \
935 if ((S) && (L)) \
Damjan Marionf1213b82016-03-13 02:22:06 +0100936 clib_memcpy ((V), (S), (L)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700937 (V)[(L)] = 0; \
938 } while (0)
939
940
Chris Lukeb5850972016-05-03 16:34:59 -0400941/** \brief Test whether a vector is a NULL terminated c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942
Dave Barachc3799992016-08-15 11:12:27 -0400943 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700944 @return BOOLEAN indicating if the vector c-string is null terminated.
945*/
946#define vec_c_string_is_terminated(V) \
947 (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
948
Chris Lukeb5850972016-05-03 16:34:59 -0400949/** \brief (If necessary) NULL terminate a vector containing a c-string.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700950
Dave Barachc3799992016-08-15 11:12:27 -0400951 @param V (possibly NULL) pointer to a vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700952 @return V (value-result macro parameter)
953*/
954#define vec_terminate_c_string(V) \
955 do { \
956 u32 vl = vec_len ((V)); \
957 if (!vec_c_string_is_terminated(V)) \
958 { \
959 vec_validate ((V), vl); \
960 (V)[vl] = 0; \
961 } \
962 } while (0)
963
964#endif /* included_vec_h */
965
Dave Barachc3799992016-08-15 11:12:27 -0400966
967/*
968 * fd.io coding-style-patch-verification: ON
969 *
970 * Local Variables:
971 * eval: (c-set-style "gnu")
972 * End:
973 */