blob: 421cb3dda99b19d0e035762c084c649d5da4ac13 [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#include <vppinfra/format.h>
Damjan Mariona7e83ce2016-06-09 12:38:22 +020039#include <ctype.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070040
41/* Format vectors. */
Dave Barachc3799992016-08-15 11:12:27 -040042u8 *
43format_vec32 (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070044{
Dave Barachc3799992016-08-15 11:12:27 -040045 u32 *v = va_arg (*va, u32 *);
46 char *fmt = va_arg (*va, char *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070047 uword i;
48 for (i = 0; i < vec_len (v); i++)
49 {
50 if (i > 0)
51 s = format (s, ", ");
52 s = format (s, fmt, v[i]);
53 }
54 return s;
55}
56
Dave Barachc3799992016-08-15 11:12:27 -040057u8 *
58format_vec_uword (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070059{
Dave Barachc3799992016-08-15 11:12:27 -040060 uword *v = va_arg (*va, uword *);
61 char *fmt = va_arg (*va, char *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070062 uword i;
63 for (i = 0; i < vec_len (v); i++)
64 {
65 if (i > 0)
66 s = format (s, ", ");
67 s = format (s, fmt, v[i]);
68 }
69 return s;
70}
71
72/* Ascii buffer and length. */
Dave Barachc3799992016-08-15 11:12:27 -040073u8 *
74format_ascii_bytes (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070075{
Dave Barachc3799992016-08-15 11:12:27 -040076 u8 *v = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070077 uword n_bytes = va_arg (*va, uword);
78 vec_add (s, v, n_bytes);
79 return s;
80}
81
82/* Format hex dump. */
Dave Barachc3799992016-08-15 11:12:27 -040083u8 *
84format_hex_bytes (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070085{
Dave Barachc3799992016-08-15 11:12:27 -040086 u8 *bytes = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 int n_bytes = va_arg (*va, int);
88 uword i;
89
90 /* Print short or long form depending on byte count. */
91 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +020092 u32 indent = format_get_indent (s);
Ed Warnickecb9cada2015-12-08 15:45:58 -070093
94 if (n_bytes == 0)
95 return s;
96
97 for (i = 0; i < n_bytes; i++)
98 {
Dave Barachc3799992016-08-15 11:12:27 -040099 if (!short_form && (i % 32) == 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100 s = format (s, "%08x: ", i);
101
102 s = format (s, "%02x", bytes[i]);
103
Dave Barachc3799992016-08-15 11:12:27 -0400104 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105 s = format (s, "\n%U", format_white_space, indent);
106 }
107
108 return s;
109}
110
Damjan Marion3860a772019-06-17 23:20:27 +0200111u8 *
112format_hex_bytes_no_wrap (u8 * s, va_list * va)
113{
114 u8 *bytes = va_arg (*va, u8 *);
115 int n_bytes = va_arg (*va, int);
116 uword i;
117
118 if (n_bytes == 0)
119 return s;
120
121 for (i = 0; i < n_bytes; i++)
122 s = format (s, "%02x", bytes[i]);
123
124 return s;
125}
126
Ed Warnickecb9cada2015-12-08 15:45:58 -0700127/* Add variable number of spaces. */
Dave Barachc3799992016-08-15 11:12:27 -0400128u8 *
129format_white_space (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130{
Gabriel Gannee3ea7972017-10-12 10:53:31 +0200131 u32 n = va_arg (*va, u32);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700132 while (n-- > 0)
133 vec_add1 (s, ' ');
134 return s;
135}
136
Dave Barachc3799992016-08-15 11:12:27 -0400137u8 *
138format_time_interval (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700139{
Dave Barachc3799992016-08-15 11:12:27 -0400140 u8 *fmt = va_arg (*args, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141 f64 t = va_arg (*args, f64);
Dave Barachc3799992016-08-15 11:12:27 -0400142 u8 *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700143
144 const f64 seconds_per_minute = 60;
145 const f64 seconds_per_hour = 60 * seconds_per_minute;
146 const f64 seconds_per_day = 24 * seconds_per_hour;
147 uword days, hours, minutes, secs, msecs, usecs;
Dave Barachc3799992016-08-15 11:12:27 -0400148
Ed Warnickecb9cada2015-12-08 15:45:58 -0700149 days = t / seconds_per_day;
150 t -= days * seconds_per_day;
151
152 hours = t / seconds_per_hour;
153 t -= hours * seconds_per_hour;
154
155 minutes = t / seconds_per_minute;
156 t -= minutes * seconds_per_minute;
157
158 secs = t;
159 t -= secs;
160
Dave Barachc3799992016-08-15 11:12:27 -0400161 msecs = 1e3 * t;
162 usecs = 1e6 * t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163
164 for (f = fmt; *f; f++)
165 {
166 uword what, c;
Dave Barachc3799992016-08-15 11:12:27 -0400167 char *what_fmt = "%d";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700168
169 switch (c = *f)
170 {
171 default:
172 vec_add1 (s, c);
173 continue;
174
175 case 'd':
176 what = days;
177 what_fmt = "%d";
178 break;
179 case 'h':
180 what = hours;
181 what_fmt = "%02d";
182 break;
183 case 'm':
184 what = minutes;
185 what_fmt = "%02d";
186 break;
187 case 's':
188 what = secs;
189 what_fmt = "%02d";
190 break;
191 case 'f':
192 what = msecs;
193 what_fmt = "%03d";
194 break;
195 case 'u':
196 what = usecs;
197 what_fmt = "%06d";
198 break;
199 }
200
201 s = format (s, what_fmt, what);
202 }
203
204 return s;
205}
206
Nathan Skrzypczak162ff5e2021-11-09 18:18:21 +0100207/* Format base 10 e.g. 100, 100K, 100M, 100G */
208__clib_export u8 *
209format_base10 (u8 *s, va_list *va)
210{
211 uword size = va_arg (*va, uword);
212
213 if (size < 1000)
214 s = format (s, "%d", size);
215 else if (size < 1000000)
216 s = format (s, "%.2fK", (f64) size / 1000.);
217 else if (size < 1000000000)
218 s = format (s, "%.2fM", (f64) size / 1000000.);
219 else
220 s = format (s, "%.2fG", (f64) size / 1000000000.);
221
222 return s;
223}
224
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225/* Unparse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200226__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400227format_memory_size (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700228{
229 uword size = va_arg (*va, uword);
230 uword l, u, log_u;
231
232 l = size > 0 ? min_log2 (size) : 0;
233 if (l < 10)
234 log_u = 0;
235 else if (l < 20)
236 log_u = 10;
237 else if (l < 30)
238 log_u = 20;
239 else
240 log_u = 30;
241
242 u = (uword) 1 << log_u;
243 if (size & (u - 1))
244 s = format (s, "%.2f", (f64) size / (f64) u);
245 else
246 s = format (s, "%d", size >> log_u);
247
248 if (log_u != 0)
249 s = format (s, "%c", " kmg"[log_u / 10]);
250
251 return s;
252}
253
254/* Parse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200255__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400256unformat_memory_size (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700257{
258 uword amount, shift, c;
Dave Barachc3799992016-08-15 11:12:27 -0400259 uword *result = va_arg (*va, uword *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260
Dave Barachc3799992016-08-15 11:12:27 -0400261 if (!unformat (input, "%wd%_", &amount))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700262 return 0;
263
264 c = unformat_get_input (input);
265 switch (c)
266 {
Dave Barachc3799992016-08-15 11:12:27 -0400267 case 'k':
268 case 'K':
269 shift = 10;
270 break;
271 case 'm':
272 case 'M':
273 shift = 20;
274 break;
275 case 'g':
276 case 'G':
277 shift = 30;
278 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700279 default:
280 shift = 0;
281 unformat_put_input (input);
282 break;
283 }
284
285 *result = amount << shift;
286 return 1;
287}
288
Damjan Marionb5095042020-09-11 22:13:46 +0200289/* Unparse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200290__clib_export u8 *
Damjan Marionb5095042020-09-11 22:13:46 +0200291format_log2_page_size (u8 * s, va_list * va)
292{
293 clib_mem_page_sz_t log2_page_sz = va_arg (*va, clib_mem_page_sz_t);
294
295 if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
296 return format (s, "unknown");
297
298 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT)
299 return format (s, "default");
300
301 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE)
302 return format (s, "default-hugepage");
303
304 if (log2_page_sz >= 30)
305 return format (s, "%uG", 1 << (log2_page_sz - 30));
306
307 if (log2_page_sz >= 20)
308 return format (s, "%uM", 1 << (log2_page_sz - 20));
309
310 if (log2_page_sz >= 10)
311 return format (s, "%uK", 1 << (log2_page_sz - 10));
312
313 return format (s, "%u", 1 << log2_page_sz);
314}
315
316/* Parse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200317__clib_export uword
Damjan Marionb5095042020-09-11 22:13:46 +0200318unformat_log2_page_size (unformat_input_t * input, va_list * va)
319{
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100320 uword amount;
Damjan Marionb5095042020-09-11 22:13:46 +0200321 clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
322
Damjan Marionb5095042020-09-11 22:13:46 +0200323 if (unformat (input, "default-hugepage"))
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100324 *result = CLIB_MEM_PAGE_SZ_DEFAULT_HUGE;
325 else if (unformat (input, "default"))
326 *result = CLIB_MEM_PAGE_SZ_DEFAULT;
327 else if (unformat (input, "%wdk", &amount))
328 *result = min_log2 (amount) + 10;
329 else if (unformat (input, "%wdK", &amount))
330 *result = min_log2 (amount) + 10;
331 else if (unformat (input, "%wdm", &amount))
332 *result = min_log2 (amount) + 20;
333 else if (unformat (input, "%wdM", &amount))
334 *result = min_log2 (amount) + 20;
335 else if (unformat (input, "%wdg", &amount))
336 *result = min_log2 (amount) + 30;
337 else if (unformat (input, "%wdG", &amount))
338 *result = min_log2 (amount) + 30;
339 else
340 return 0;
Damjan Marionb5095042020-09-11 22:13:46 +0200341 return 1;
342}
343
Ed Warnickecb9cada2015-12-08 15:45:58 -0700344/* Format c identifier: e.g. a_name -> "a name".
Klement Sekeraea841302018-05-11 12:59:05 +0200345 Works for both vector names and null terminated c strings. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200346__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400347format_c_identifier (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348{
Dave Barachc3799992016-08-15 11:12:27 -0400349 u8 *id = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350 uword i, l;
351
352 l = ~0;
353 if (clib_mem_is_vec (id))
354 l = vec_len (id);
355
356 if (id)
BenoƮt Ganne1bd6f612020-07-16 12:03:35 +0200357 for (i = 0; i < l && id[i] != 0; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358 {
359 u8 c = id[i];
360
361 if (c == '_')
362 c = ' ';
363 vec_add1 (s, c);
364 }
365
366 return s;
367}
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200368
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200369__clib_export u8 *
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200370format_hexdump (u8 * s, va_list * args)
371{
Dave Barachc3799992016-08-15 11:12:27 -0400372 u8 *data = va_arg (*args, u8 *);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200373 uword len = va_arg (*args, uword);
Dave Barachc3799992016-08-15 11:12:27 -0400374 int i, index = 0;
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200375 const int line_len = 16;
Dave Barachc3799992016-08-15 11:12:27 -0400376 u8 *line_hex = 0;
377 u8 *line_str = 0;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200378 u32 indent = format_get_indent (s);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200379
380 if (!len)
381 return s;
382
Dave Barachc3799992016-08-15 11:12:27 -0400383 for (i = 0; i < len; i++)
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200384 {
Dave Barachc3799992016-08-15 11:12:27 -0400385 line_hex = format (line_hex, "%02x ", data[i]);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200386 line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
Dave Barachc3799992016-08-15 11:12:27 -0400387 if (!((i + 1) % line_len))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200388 {
389 s = format (s, "%U%05x: %v[%v]",
390 format_white_space, index ? indent : 0,
391 index, line_hex, line_str);
392 if (i < len - 1)
393 s = format (s, "\n");
394 index = i + 1;
Dave Barachc3799992016-08-15 11:12:27 -0400395 vec_reset_length (line_hex);
396 vec_reset_length (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200397 }
398 }
399
400 while (i++ % line_len)
401 line_hex = format (line_hex, " ");
402
Dave Barachc3799992016-08-15 11:12:27 -0400403 if (vec_len (line_hex))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200404 s = format (s, "%U%05x: %v[%v]",
Damjan Marion1e336632018-02-17 14:05:08 +0100405 format_white_space, index ? indent : 0,
406 index, line_hex, line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200407
Dave Barachc3799992016-08-15 11:12:27 -0400408 vec_free (line_hex);
409 vec_free (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200410
411 return s;
412}
Dave Barachc3799992016-08-15 11:12:27 -0400413
Damjan Marione6387b22021-12-22 21:58:54 +0100414__clib_export u8 *
415format_u64_bitmap (u8 *s, va_list *args)
416{
417 u64 *bitmap = va_arg (*args, u64 *);
418 int n_uword = va_arg (*args, int);
419 u32 indent = format_get_indent (s);
420
421 s = format (s, "%6s", "");
422
423 for (int i = 60; i >= 0; i -= 4)
424 s = format (s, "%5d", i);
425
426 vec_add1 (s, '\n');
427
428 for (int j = n_uword - 1; j >= 0; j--)
429 {
430 s = format (s, "%U0x%04x ", format_white_space, indent, j * 8);
431 for (int i = 63; i >= 0; i--)
432 {
433 vec_add1 (s, (1ULL << i) & bitmap[j] ? '1' : '.');
434 if (i % 4 == 0)
435 vec_add1 (s, ' ');
436 }
437 s = format (s, "0x%016lx", bitmap[j]);
438 if (j)
439 vec_add1 (s, '\n');
440 }
441
442 return s;
443}
444
Dave Barachc3799992016-08-15 11:12:27 -0400445/*
446 * fd.io coding-style-patch-verification: ON
447 *
448 * Local Variables:
449 * eval: (c-set-style "gnu")
450 * End:
451 */