misc: vpe.api messages dynamically allocated
[vpp.git] / src / vppinfra / bitmap.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4
5 #include <vppinfra/vec.h>
6 #include <vppinfra/bitmap.h>
7
8 /** unformat an any sized hexadecimal bitmask into a bitmap
9
10     uword * bitmap;
11     rv = unformat ("%U", unformat_bitmap_mask, &bitmap);
12
13     Standard unformat_function_t arguments
14
15     @param input - pointer an unformat_input_t
16     @param va - varargs list comprising a single uword **
17     @returns 1 on success, 0 on failure
18 */
19 __clib_export uword
20 unformat_bitmap_mask (unformat_input_t *input, va_list *va)
21 {
22   u8 *v = 0; /* hexadecimal vector */
23   uword **bitmap_return = va_arg (*va, uword **);
24   uword *bitmap = 0;
25
26   if (unformat (input, "%U", unformat_hex_string, &v))
27     {
28       int i, s = vec_len (v) - 1; /* 's' for significance or shift */
29
30       /* v[0] holds the most significant byte */
31       for (i = 0; s >= 0; i++, s--)
32         bitmap = clib_bitmap_set_multiple (bitmap, s * BITS (v[i]), v[i],
33                                            BITS (v[i]));
34
35       vec_free (v);
36       *bitmap_return = bitmap;
37       return 1;
38     }
39
40   return 0;
41 }
42
43 /** unformat a list of bit ranges into a bitmap (eg "0-3,5-7,11" )
44
45     uword * bitmap;
46     rv = unformat ("%U", unformat_bitmap_list, &bitmap);
47
48     Standard unformat_function_t arguments
49
50     @param input - pointer an unformat_input_t
51     @param va - varargs list comprising a single uword **
52     @returns 1 on success, 0 on failure
53 */
54 __clib_export uword
55 unformat_bitmap_list (unformat_input_t *input, va_list *va)
56 {
57   uword **bitmap_return = va_arg (*va, uword **);
58   uword *bitmap = 0;
59
60   u32 a, b;
61
62   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
63     {
64       int i;
65       if (unformat (input, "%u-%u,", &a, &b))
66         ;
67       else if (unformat (input, "%u,", &a))
68         b = a;
69       else if (unformat (input, "%u-%u", &a, &b))
70         ;
71       else if (unformat (input, "%u", &a))
72         b = a;
73       else if (bitmap)
74         {
75           unformat_put_input (input);
76           break;
77         }
78       else
79         goto error;
80
81       if (b < a)
82         goto error;
83
84       for (i = a; i <= b; i++)
85         bitmap = clib_bitmap_set (bitmap, i, 1);
86     }
87   *bitmap_return = bitmap;
88   return 1;
89 error:
90   clib_bitmap_free (bitmap);
91   return 0;
92 }
93
94 /** Format a bitmap as a string of hex bytes
95
96     uword * bitmap;
97     s = format ("%U", format_bitmap_hex, bitmap);
98
99     Standard format_function_t arguments
100
101     @param s - string under construction
102     @param args - varargs list comprising a single uword *
103     @returns string under construction
104 */
105
106 __clib_export u8 *
107 format_bitmap_hex (u8 *s, va_list *args)
108 {
109   uword *bitmap = va_arg (*args, uword *);
110   int i, is_trailing_zero = 1;
111
112   if (!bitmap)
113     return format (s, "0");
114
115   i = vec_bytes (bitmap) * 2;
116
117   while (i > 0)
118     {
119       u8 x = clib_bitmap_get_multiple (bitmap, --i * 4, 4);
120
121       if (x && is_trailing_zero)
122         is_trailing_zero = 0;
123
124       if (x || !is_trailing_zero)
125         s = format (s, "%x", x);
126     }
127   return s;
128 }
129
130 /** Format a bitmap as a list
131
132     uword * bitmap;
133     s = format ("%U", format_bitmap_list, bitmap);
134
135     Standard format_function_t arguments
136
137     @param s - string under construction
138     @param args - varargs list comprising a single uword *
139     @returns string under construction
140 */
141
142 __clib_export u8 *
143 format_bitmap_list (u8 *s, va_list *args)
144 {
145   uword *bitmap = va_arg (*args, uword *);
146   uword fs, fc;
147
148   if (!bitmap)
149     return s;
150
151   fs = clib_bitmap_first_set (bitmap);
152   if (fs == ~0)
153     return s;
154
155   while (1)
156     {
157       fc = clib_bitmap_next_clear (bitmap, fs + 1);
158       if (fc > fs + 1)
159         s = format (s, "%lu-%lu", fs, fc - 1);
160       else
161         s = format (s, "%lu", fs);
162
163       if ((fs = clib_bitmap_next_set (bitmap, fc)) == ~0)
164         return s;
165       s = format (s, ", ");
166     }
167 }