FD.io VPP  v16.06
Vector Packet Processing
vec.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17 
18  Permission is hereby granted, free of charge, to any person obtaining
19  a copy of this software and associated documentation files (the
20  "Software"), to deal in the Software without restriction, including
21  without limitation the rights to use, copy, modify, merge, publish,
22  distribute, sublicense, and/or sell copies of the Software, and to
23  permit persons to whom the Software is furnished to do so, subject to
24  the following conditions:
25 
26  The above copyright notice and this permission notice shall be
27  included in all copies or substantial portions of the Software.
28 
29  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37 
38 #ifndef included_vec_h
39 #define included_vec_h
40 
41 #include <vppinfra/clib.h> /* word, etc */
42 #include <vppinfra/mem.h> /* clib_mem_free */
43 #include <vppinfra/string.h> /* memcpy, memmove */
44 #include <vppinfra/vec_bootstrap.h>
45 
46 /** \file
47 
48  CLIB vectors are ubiquitous dynamically resized arrays with by user
49  defined "headers". Many CLIB data structures (e.g. hash, heap,
50  pool) are vectors with various different headers.
51 
52  The memory layout looks like this:
53 
54 ~~~~~~~~
55  user header (aligned to uword boundary)
56  vector length: number of elements
57  user's pointer-> vector element #0
58  vector element #1
59  ...
60 ~~~~~~~~
61 
62  The user pointer contains the address of vector element # 0. Null
63  pointer vectors are valid and mean a zero length vector.
64 
65  You can reset the length of an allocated vector to zero via the
66  vec_reset_length(v) macro, or by setting the vector length field to
67  zero (e.g. _vec_len (v) = 0). Vec_reset_length(v) preferred: it
68  understands Null pointers.
69 
70  Typically, the header is not present. Headers allow for other
71  data structures to be built atop CLIB vectors.
72 
73  Users may specify the alignment for 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 
84  Standard programming error: memorize a pointer to the ith element
85  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
87  which are invariant.
88  */
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 */
99 void * vec_resize_allocate_memory (void * v,
100  word length_increment,
101  uword data_bytes,
102  uword header_bytes,
103  uword data_align);
104 
105 /** \brief Low-level vector resize function, usually not called directly
106 
107  @param v pointer to a vector
108  @param length_increment length increment in elements
109  @param data_bytes requested size in bytes
110  @param header_bytes header size in bytes (may be zero)
111  @param data_align alignment (may be zero)
112  @return v_prime pointer to resized vector, may or may not equal v
113 */
114 
115 always_inline void *
116 _vec_resize (void * v,
117  word length_increment,
118  uword data_bytes,
119  uword header_bytes,
120  uword data_align)
121 {
122  vec_header_t * vh = _vec_find (v);
123  uword new_data_bytes, aligned_header_bytes;
124 
125  aligned_header_bytes = vec_header_bytes (header_bytes);
126 
127  new_data_bytes = data_bytes + aligned_header_bytes;
128 
129  if (PREDICT_TRUE (v != 0))
130  {
131  void * p = v - aligned_header_bytes;
132 
133  /* Vector header must start heap object. */
135 
136  /* Typically we'll not need to resize. */
137  if (new_data_bytes <= clib_mem_size (p))
138  {
139  vh->len += length_increment;
140  return v;
141  }
142  }
143 
144  /* Slow path: call helper function. */
145  return vec_resize_allocate_memory (v, length_increment, data_bytes, header_bytes,
146  clib_max (sizeof (vec_header_t), data_align));
147 }
148 
149 /** \brief Predicate function, says whether the supplied vector is a clib heap
150  object (general version).
151 
152  @param v pointer to a vector
153  @param header_bytes vector header size in bytes (may be zero)
154  @return 0 or 1
155 */
156 uword clib_mem_is_vec_h (void * v, uword header_bytes);
157 
158 
159 /** \brief Predicate function, says whether the supplied vector is a clib heap
160  object
161 
162  @param v pointer to a vector
163  @return 0 or 1
164 */
166 { return clib_mem_is_vec_h (v, 0); }
167 
168 /* Local variable naming macro (prevents collisions with other macro naming). */
169 #define _v(var) _vec_##var
170 
171 /** \brief Resize a vector (general version).
172  Add N elements to end of given vector V, return pointer to start of vector.
173  Vector will have room for H header bytes and will have user's data aligned
174  at alignment A (rounded to next power of 2).
175 
176  @param V pointer to a vector
177  @param N number of elements to add
178  @param H header size in bytes (may be zero)
179  @param A alignment (may be zero)
180  @return V (value-result macro parameter)
181 */
182 
183 #define vec_resize_ha(V,N,H,A) \
184 do { \
185  word _v(n) = (N); \
186  word _v(l) = vec_len (V); \
187  V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
188 } while (0)
189 
190 /** \brief Resize a vector (no header, unspecified alignment)
191  Add N elements to end of given vector V, return pointer to start of vector.
192  Vector will have room for H header bytes and will have user's data aligned
193  at alignment A (rounded to next power of 2).
194 
195  @param V pointer to a vector
196  @param N number of elements to add
197  @return V (value-result macro parameter)
198 */
199 #define vec_resize(V,N) vec_resize_ha(V,N,0,0)
200 
201 /** \brief Resize a vector (no header, alignment specified).
202  Add N elements to end of given vector V, return pointer to start of vector.
203  Vector will have room for H header bytes and will have user's data aligned
204  at alignment A (rounded to next power of 2).
205 
206  @param V pointer to a vector
207  @param N number of elements to add
208  @param A alignment (may be zero)
209  @return V (value-result macro parameter)
210 */
211 
212 #define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A)
213 
214 /** \brief Allocate space for N more elements
215 
216  @param V pointer to a vector
217  @param N number of elements to add
218  @param H header size in bytes (may be zero)
219  @param A alignment (may be zero)
220  @return V (value-result macro parameter)
221 */
222 
223 #define vec_alloc_ha(V,N,H,A) \
224 do { \
225  uword _v(l) = vec_len (V); \
226  vec_resize_ha (V, N, H, A); \
227  _vec_len (V) = _v(l); \
228 } while (0)
229 
230 /** \brief Allocate space for N more elements
231  (no header, unspecified alignment)
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_alloc(V,N) vec_alloc_ha(V,N,0,0)
238 
239 /** \brief Allocate space for N more elements (no header, given alignment)
240  @param V pointer to a vector
241  @param N number of elements to add
242  @param A alignment (may be zero)
243  @return V (value-result macro parameter)
244 */
245 
246 #define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A)
247 
248 /** \brief Create new vector of given type and length (general version).
249  @param T type of elements in new vector
250  @param N number of elements to add
251  @param H header size in bytes (may be zero)
252  @param A alignment (may be zero)
253  @return V new vector
254 */
255 #define vec_new_ha(T,N,H,A) \
256 ({ \
257  word _v(n) = (N); \
258  _vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \
259 })
260 
261 /** \brief Create new vector of given type and length
262  (unspecified alignment, no header).
263 
264  @param T type of elements in new vector
265  @param N number of elements to add
266  @return V new vector
267 */
268 #define vec_new(T,N) vec_new_ha(T,N,0,0)
269 /** \brief Create new vector of given type and length
270  (alignment specified, no header).
271 
272  @param T type of elements in new vector
273  @param N number of elements to add
274  @param A alignment (may be zero)
275  @return V new vector
276 */
277 #define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A)
278 
279 /** \brief Free vector's memory (general version)
280 
281  @param V pointer to a vector
282  @param H size of header in bytes
283  @return V (value-result parameter, V=0)
284 */
285 #define vec_free_h(V,H) \
286 do { \
287  if (V) \
288  { \
289  clib_mem_free (vec_header ((V), (H))); \
290  V = 0; \
291  } \
292 } while (0)
293 
294 /** \brief Free vector's memory (no header).
295  @param V pointer to a vector
296  @return V (value-result parameter, V=0)
297 */
298 #define vec_free(V) vec_free_h(V,0)
299 
300 /**\brief Free vector user header (syntactic sugar)
301  @param h vector header
302  @void
303 */
304 #define vec_free_header(h) clib_mem_free (h)
305 
306 /** \brief Return copy of vector (general version).
307 
308  @param V pointer to a vector
309  @param H size of header in bytes
310  @param A alignment (may be zero)
311 
312  @return Vdup copy of vector
313 */
314 
315 #define vec_dup_ha(V,H,A) \
316 ({ \
317  __typeof__ ((V)[0]) * _v(v) = 0; \
318  uword _v(l) = vec_len (V); \
319  if (_v(l) > 0) \
320  { \
321  vec_resize_ha (_v(v), _v(l), (H), (A)); \
322  clib_memcpy (_v(v), (V), _v(l) * sizeof ((V)[0]));\
323  } \
324  _v(v); \
325 })
326 
327 /** \brief Return copy of vector (no header, no alignment)
328 
329  @param V pointer to a vector
330  @return Vdup copy of vector
331 */
332 #define vec_dup(V) vec_dup_ha(V,0,0)
333 
334 /** \brief Return copy of vector (no header, alignment specified).
335 
336  @param V pointer to a vector
337  @param A alignment (may be zero)
338 
339  @return Vdup copy of vector
340 */
341 #define vec_dup_aligned(V,A) vec_dup_ha(V,0,A)
342 
343 /** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) ==
344  sizeof(DST[0])
345 
346  @param DST destination
347  @param SRC source
348 */
349 #define vec_copy(DST,SRC) clib_memcpy (DST, SRC, vec_len (DST) * \
350  sizeof ((DST)[0]))
351 
352 /** \brief Clone a vector. Make a new vector with the
353  same size as a given vector but possibly with a different type.
354 
355  @param NEW_V pointer to new vector
356  @param OLD_V pointer to old vector
357 */
358 #define vec_clone(NEW_V,OLD_V) \
359 do { \
360  (NEW_V) = 0; \
361  (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \
362  vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \
363 } while (0)
364 
365 /** \brief Make sure vector is long enough for given index (general version).
366 
367  @param V (possibly NULL) pointer to a vector.
368  @param I vector index which will be valid upon return
369  @param H header size in bytes (may be zero)
370  @param A alignment (may be zero)
371  @return V (value-result macro parameter)
372 */
373 
374 #define vec_validate_ha(V,I,H,A) \
375 do { \
376  word _v(i) = (I); \
377  word _v(l) = vec_len (V); \
378  if (_v(i) >= _v(l)) \
379  { \
380  vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
381  /* Must zero new space since user may have previously \
382  used e.g. _vec_len (v) -= 10 */ \
383  memset ((V) + _v(l), 0, (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \
384  } \
385 } while (0)
386 
387 /** \brief Make sure vector is long enough for given index
388  (no header, unspecified alignment)
389 
390  @param V (possibly NULL) pointer to a vector.
391  @param I vector index which will be valid upon return
392  @return V (value-result macro parameter)
393 */
394 #define vec_validate(V,I) vec_validate_ha(V,I,0,0)
395 
396 /** \brief Make sure vector is long enough for given index
397  (no header, specified alignment)
398 
399  @param V (possibly NULL) pointer to a vector.
400  @param I vector index which will be valid upon return
401  @param A alignment (may be zero)
402  @return V (value-result macro parameter)
403 */
404 
405 #define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A)
406 
407 /** \brief Make sure vector is long enough for given index
408  and initialize empty space (general version)
409 
410  @param V (possibly NULL) pointer to a vector.
411  @param I vector index which will be valid upon return
412  @param INIT initial value (can be a complex expression!)
413  @param H header size in bytes (may be zero)
414  @param A alignment (may be zero)
415  @return V (value-result macro parameter)
416 */
417 #define vec_validate_init_empty_ha(V,I,INIT,H,A) \
418 do { \
419  word _v(i) = (I); \
420  word _v(l) = vec_len (V); \
421  if (_v(i) >= _v(l)) \
422  { \
423  vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \
424  while (_v(l) <= _v(i)) \
425  { \
426  (V)[_v(l)] = (INIT); \
427  _v(l)++; \
428  } \
429  } \
430 } while (0)
431 
432 /** \brief Make sure vector is long enough for given index
433  and initialize empty space (no header, unspecified alignment)
434 
435  @param V (possibly NULL) pointer to a vector.
436  @param I vector index which will be valid upon return
437  @param INIT initial value (can be a complex expression!)
438  @param H header size in bytes (may be zero)
439  @param A alignment (may be zero)
440  @return V (value-result macro parameter)
441 */
442 
443 #define vec_validate_init_empty(V,I,INIT) \
444  vec_validate_init_empty_ha(V,I,INIT,0,0)
445 
446 /** \brief Make sure vector is long enough for given index
447  and initialize empty space (no header, alignment alignment)
448 
449  @param V (possibly NULL) pointer to a vector.
450  @param I vector index which will be valid upon return
451  @param INIT initial value (can be a complex expression!)
452  @param H header size in bytes (may be zero)
453  @param A alignment (may be zero)
454  @return V (value-result macro parameter)
455 */
456 #define vec_validate_init_empty_aligned(V,I,A) \
457  vec_validate_init_empty_ha(V,I,INIT,0,A)
458 
459 /** \brief Add 1 element to end of vector (general version).
460 
461  @param V pointer to a vector
462  @param E element to add
463  @param H header size in bytes (may be zero)
464  @param A alignment (may be zero)
465  @return V (value-result macro parameter)
466 */
467 #define vec_add1_ha(V,E,H,A) \
468 do { \
469  word _v(l) = vec_len (V); \
470  V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
471  (V)[_v(l)] = (E); \
472 } while (0)
473 
474 /** \brief Add 1 element to end of vector (unspecified alignment).
475 
476  @param V pointer to a vector
477  @param E element to add
478  @return V (value-result macro parameter)
479 */
480 #define vec_add1(V,E) vec_add1_ha(V,E,0,0)
481 
482 /** \brief Add 1 element to end of vector (alignment specified).
483 
484  @param V pointer to a vector
485  @param E element to add
486  @param H header size in bytes (may be zero)
487  @param A alignment (may be zero)
488  @return V (value-result macro parameter)
489 */
490 #define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A)
491 
492 /** \brief Add N elements to end of vector V,
493  return pointer to new elements in P. (general version)
494 
495  @param V pointer to a vector
496  @param P pointer to new vector element(s)
497  @param N number of elements to add
498  @param H header size in bytes (may be zero)
499  @param A alignment (may be zero)
500  @return V and P (value-result macro parameters)
501 */
502 #define vec_add2_ha(V,P,N,H,A) \
503 do { \
504  word _v(n) = (N); \
505  word _v(l) = vec_len (V); \
506  V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
507  P = (V) + _v(l); \
508 } while (0)
509 
510 /** \brief Add N elements to end of vector V,
511  return pointer to new elements in P. (no header, unspecified alignment)
512 
513  @param V pointer to a vector
514  @param P pointer to new vector element(s)
515  @param N number of elements to add
516  @return V and P (value-result macro parameters)
517 */
518 
519 #define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0)
520 
521 /** \brief Add N elements to end of vector V,
522  return pointer to new elements in P. (no header, alignment specified)
523 
524  @param V pointer to a vector
525  @param P pointer to new vector element(s)
526  @param N number of elements to add
527  @param A alignment (may be zero)
528  @return V and P (value-result macro parameters)
529 */
530 
531 #define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A)
532 
533 /** \brief Add N elements to end of vector V (general version)
534 
535  @param V pointer to a vector
536  @param E pointer to element(s) to add
537  @param N number of elements to add
538  @param H header size in bytes (may be zero)
539  @param A alignment (may be zero)
540  @return V (value-result macro parameter)
541 */
542 #define vec_add_ha(V,E,N,H,A) \
543 do { \
544  word _v(n) = (N); \
545  word _v(l) = vec_len (V); \
546  V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \
547  clib_memcpy ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \
548 } while (0)
549 
550 /** \brief Add N elements to end of vector V (no header, unspecified alignment)
551 
552  @param V pointer to a vector
553  @param E pointer to element(s) to add
554  @param N number of elements to add
555  @return V (value-result macro parameter)
556 */
557 #define vec_add(V,E,N) vec_add_ha(V,E,N,0,0)
558 
559 /** \brief Add N elements to end of vector V (no header, specified alignment)
560 
561  @param V pointer to a vector
562  @param E pointer to element(s) to add
563  @param N number of elements to add
564  @param A alignment (may be zero)
565  @return V (value-result macro parameter)
566 */
567 #define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A)
568 
569 /** \brief Returns last element of a vector and decrements its length
570 
571  @param V pointer to a vector
572  @return E element removed from the end of the vector
573 */
574 #define vec_pop(V) \
575 ({ \
576  uword _v(l) = vec_len (V); \
577  ASSERT (_v(l) > 0); \
578  _v(l) -= 1; \
579  _vec_len (V) = _v (l); \
580  (V)[_v(l)]; \
581 })
582 
583 /** \brief Set E to the last element of a vector, decrement vector length
584  @param V pointer to a vector
585  @param E pointer to the last vector element
586  @return E element removed from the end of the vector
587  (value-result macro parameter
588 */
589 
590 #define vec_pop2(V,E) \
591 ({ \
592  uword _v(l) = vec_len (V); \
593  if (_v(l) > 0) (E) = vec_pop (V); \
594  _v(l) > 0; \
595 })
596 
597 /** \brief Insert N vector elements starting at element M,
598  initialize new elements (general version).
599 
600  @param V (possibly NULL) pointer to a vector.
601  @param N number of elements to insert
602  @param M insertion point
603  @param INIT initial value (can be a complex expression!)
604  @param H header size in bytes (may be zero)
605  @param A alignment (may be zero)
606  @return V (value-result macro parameter)
607 */
608 #define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \
609 do { \
610  word _v(l) = vec_len (V); \
611  word _v(n) = (N); \
612  word _v(m) = (M); \
613  V = _vec_resize ((V), \
614  _v(n), \
615  (_v(l) + _v(n))*sizeof((V)[0]), \
616  (H), (A)); \
617  ASSERT (_v(m) <= _v(l)); \
618  memmove ((V) + _v(m) + _v(n), \
619  (V) + _v(m), \
620  (_v(l) - _v(m)) * sizeof ((V)[0])); \
621  memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \
622 } while (0)
623 
624 /** \brief Insert N vector elements starting at element M,
625  initialize new elements to zero (general version)
626 
627  @param V (possibly NULL) pointer to a vector.
628  @param N number of elements to insert
629  @param M insertion point
630  @param H header size in bytes (may be zero)
631  @param A alignment (may be zero)
632  @return V (value-result macro parameter)
633 */
634 #define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A)
635 
636 /** \brief Insert N vector elements starting at element M,
637  initialize new elements to zero (no header, unspecified alignment)
638 
639  @param V (possibly NULL) pointer to a vector.
640  @param N number of elements to insert
641  @param M insertion point
642  @return V (value-result macro parameter)
643 */
644 #define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0)
645 
646 /** \brief Insert N vector elements starting at element M,
647  initialize new elements to zero (no header, alignment specified)
648 
649  @param V (possibly NULL) pointer to a vector.
650  @param N number of elements to insert
651  @param M insertion point
652  @param A alignment (may be zero)
653  @return V (value-result macro parameter)
654 */
655 #define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A)
656 
657 /** \brief Insert N vector elements starting at element M,
658  initialize new elements (no header, unspecified alignment)
659 
660  @param V (possibly NULL) pointer to a vector.
661  @param N number of elements to insert
662  @param M insertion point
663  @param INIT initial value (can be a complex expression!)
664  @return V (value-result macro parameter)
665 */
666 
667 #define vec_insert_init_empty(V,N,M,INIT) \
668  vec_insert_init_empty_ha(V,N,M,INIT,0,0)
669 /* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */
670 
671 /** \brief Insert N vector elements starting at element M,
672  initialize new elements (no header, specified alignment)
673 
674  @param V (possibly NULL) pointer to a vector.
675  @param N number of elements to insert
676  @param M insertion point
677  @param INIT initial value (can be a complex expression!)
678  @param A alignment (may be zero)
679  @return V (value-result macro parameter)
680 */
681 #define vec_insert_init_empty_aligned(V,N,M,INIT,A) \
682  vec_insert_init_empty_ha(V,N,M,INIT,0,A)
683 
684 /** \brief Insert N vector elements starting at element M,
685  insert given elements (general version)
686 
687  @param V (possibly NULL) pointer to a vector.
688  @param E element(s) to insert
689  @param N number of elements to insert
690  @param M insertion point
691  @param H header size in bytes (may be zero)
692  @param A alignment (may be zero)
693  @return V (value-result macro parameter)
694 */
695 
696 #define vec_insert_elts_ha(V,E,N,M,H,A) \
697 do { \
698  word _v(l) = vec_len (V); \
699  word _v(n) = (N); \
700  word _v(m) = (M); \
701  V = _vec_resize ((V), \
702  _v(n), \
703  (_v(l) + _v(n))*sizeof((V)[0]), \
704  (H), (A)); \
705  ASSERT (_v(m) <= _v(l)); \
706  memmove ((V) + _v(m) + _v(n), \
707  (V) + _v(m), \
708  (_v(l) - _v(m)) * sizeof ((V)[0])); \
709  clib_memcpy ((V) + _v(m), (E), \
710  _v(n) * sizeof ((V)[0])); \
711 } while (0)
712 
713 /** \brief Insert N vector elements starting at element M,
714  insert given elements (no header, unspecified alignment)
715 
716  @param V (possibly NULL) pointer to a vector.
717  @param E element(s) to insert
718  @param N number of elements to insert
719  @param M insertion point
720  @return V (value-result macro parameter)
721 */
722 #define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0)
723 
724 /** \brief Insert N vector elements starting at element M,
725  insert given elements (no header, specified alignment)
726 
727  @param V (possibly NULL) pointer to a vector.
728  @param E element(s) to insert
729  @param N number of elements to insert
730  @param M insertion point
731  @param A alignment (may be zero)
732  @return V (value-result macro parameter)
733 */
734 #define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A)
735 
736 /** \brief Delete N elements starting at element M
737 
738  @param V pointer to a vector
739  @param N number of elements to delete
740  @param M first element to delete
741  @return V (value-result macro parameter)
742 */
743 #define vec_delete(V,N,M) \
744 do { \
745  word _v(l) = vec_len (V); \
746  word _v(n) = (N); \
747  word _v(m) = (M); \
748  /* Copy over deleted elements. */ \
749  if (_v(l) - _v(n) - _v(m) > 0) \
750  memmove ((V) + _v(m), (V) + _v(m) + _v(n), \
751  (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \
752  /* Zero empty space at end (for future re-allocation). */ \
753  if (_v(n) > 0) \
754  memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \
755  _vec_len (V) -= _v(n); \
756 } while (0)
757 
758 /** \brief Delete the element at index I
759 
760  @param V pointer to a vector
761  @param I index to delete
762 */
763 #define vec_del1(v,i) \
764 do { \
765  uword _vec_del_l = _vec_len (v) - 1; \
766  uword _vec_del_i = (i); \
767  if (_vec_del_i < _vec_del_l) \
768  (v)[_vec_del_i] = (v)[_vec_del_l]; \
769  _vec_len (v) = _vec_del_l; \
770 } while (0)
771 
772 /** \brief Append v2 after v1. Result in v1.
773  @param V1 target vector
774  @param V2 vector to append
775 */
776 
777 #define vec_append(v1,v2) \
778 do { \
779  uword _v(l1) = vec_len (v1); \
780  uword _v(l2) = vec_len (v2); \
781  \
782  v1 = _vec_resize ((v1), _v(l2), \
783  (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
784  clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
785 } while (0)
786 
787 /** \brief Append v2 after v1. Result in v1. Specified alignment.
788  @param V1 target vector
789  @param V2 vector to append
790  @param align required alignment
791 */
792 
793 #define vec_append_aligned(v1,v2,align) \
794 do { \
795  uword _v(l1) = vec_len (v1); \
796  uword _v(l2) = vec_len (v2); \
797  \
798  v1 = _vec_resize ((v1), _v(l2), \
799  (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
800  clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \
801 } while (0)
802 
803 /** \brief Prepend v2 before v1. Result in v1.
804  @param V1 target vector
805  @param V2 vector to prepend
806 */
807 
808 #define vec_prepend(v1,v2) \
809 do { \
810  uword _v(l1) = vec_len (v1); \
811  uword _v(l2) = vec_len (v2); \
812  \
813  v1 = _vec_resize ((v1), _v(l2), \
814  (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \
815  memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
816  clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
817 } while (0)
818 
819 /** \brief Prepend v2 before v1. Result in v1. Specified alignment
820  @param V1 target vector
821  @param V2 vector to prepend
822  @param align required alignment
823 */
824 
825 #define vec_prepend_aligned(v1,v2,align) \
826 do { \
827  uword _v(l1) = vec_len (v1); \
828  uword _v(l2) = vec_len (v2); \
829  \
830  v1 = _vec_resize ((v1), _v(l2), \
831  (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \
832  memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \
833  clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \
834 } while (0)
835 
836 
837 /** \brief Zero all vector elements. Null-pointer tolerant.
838  @param var Vector to zero
839 */
840 #define vec_zero(var) \
841 do { \
842  if (var) \
843  memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \
844 } while (0)
845 
846 /** \brief Set all vector elements to given value. Null-pointer tolerant.
847  @param v vector to set
848  @param val value for each vector element
849 */
850 #define vec_set(v,val) \
851 do { \
852  word _v(i); \
853  __typeof__ ((v)[0]) _val = (val); \
854  for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \
855  (v)[_v(i)] = _val; \
856 } while (0)
857 
858 #ifdef CLIB_UNIX
859 #include <stdlib.h> /* for qsort */
860 #endif
861 
862 /** \brief Compare two vectors, not NULL-pointer tolerant
863 
864  @param v1 Pointer to a vector
865  @param v2 Pointer to a vector
866  @return 1 if equal, 0 if unequal
867 */
868 #define vec_is_equal(v1,v2) \
869  (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0])))
870 
871 /** \brief Compare two vectors (only applicable to vectors of signed numbers).
872  Used in qsort compare functions.
873 
874  @param v1 Pointer to a vector
875  @param v2 Pointer to a vector
876  @return -1, 0, +1
877 */
878 #define vec_cmp(v1,v2) \
879 ({ \
880  word _v(i), _v(cmp), _v(l); \
881  _v(l) = clib_min (vec_len (v1), vec_len (v2)); \
882  _v(cmp) = 0; \
883  for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \
884  _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \
885  if (_v(cmp)) \
886  break; \
887  } \
888  if (_v(cmp) == 0 && _v(l) > 0) \
889  _v(cmp) = vec_len(v1) - vec_len(v2); \
890  (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \
891 })
892 
893 /** \brief Sort a vector using the supplied element comparison function
894 
895  @param vec vector to sort
896  @param f comparison function
897 */
898 #define vec_sort_with_function(vec,f) \
899 do { \
900  qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \
901 } while (0)
902 
903 /** \brief Make a vector containing a NULL terminated c-string.
904 
905  @param V (possibly NULL) pointer to a vector.
906  @param S pointer to string buffer.
907  @param L string length (NOT including the terminating NULL; a la strlen())
908 */
909 #define vec_validate_init_c_string(V, S, L) \
910  do { \
911  vec_reset_length (V); \
912  vec_validate ((V), (L)); \
913  if ((S) && (L)) \
914  clib_memcpy ((V), (S), (L)); \
915  (V)[(L)] = 0; \
916  } while (0)
917 
918 
919 /** \brief Test whether a vector is a NULL terminated c-string.
920 
921  @param V (possibly NULL) pointer to a vector.
922  @return BOOLEAN indicating if the vector c-string is null terminated.
923 */
924 #define vec_c_string_is_terminated(V) \
925  (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0))
926 
927 /** \brief (If necessary) NULL terminate a vector containing a c-string.
928 
929  @param V (possibly NULL) pointer to a vector.
930  @return V (value-result macro parameter)
931 */
932 #define vec_terminate_c_string(V) \
933  do { \
934  u32 vl = vec_len ((V)); \
935  if (!vec_c_string_is_terminated(V)) \
936  { \
937  vec_validate ((V), vl); \
938  (V)[vl] = 0; \
939  } \
940  } while (0)
941 
942 #endif /* included_vec_h */
943 
uword clib_mem_is_vec_h(void *v, uword header_bytes)
Predicate function, says whether the supplied vector is a clib heap object (general version)...
Definition: vec.c:103
#define PREDICT_TRUE(x)
Definition: clib.h:98
always_inline uword clib_mem_size(void *p)
Definition: mem.h:180
#define always_inline
Definition: clib.h:84
always_inline uword clib_mem_is_vec(void *v)
Predicate function, says whether the supplied vector is a clib heap object.
Definition: vec.h:165
void * vec_resize_allocate_memory(void *v, word length_increment, uword data_bytes, uword header_bytes, uword data_align)
Low-level resize allocation function, usually not called directly.
Definition: vec.c:43
u32 len
Number of elements in vector (NOT its allocated length).
Definition: vec_bootstrap.h:59
#define ASSERT(truth)
vector header structure
Definition: vec_bootstrap.h:55
#define clib_max(x, y)
Definition: clib.h:288
u64 uword
Definition: types.h:112
i64 word
Definition: types.h:111
always_inline uword clib_mem_is_heap_object(void *p)
Definition: mem.h:133
Vector bootsrap header file.
always_inline uword vec_header_bytes(uword header_bytes)
Definition: vec_bootstrap.h:78