blob: bfe9844c832f5bd0707ef39ccd78303606f6d0c7 [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 *
Nathan Skrzypczak6de58f52022-01-24 17:10:41 +0100138format_duration (u8 *s, va_list *args)
139{
140 f64 t = va_arg (*args, f64);
141 s = format (s, "");
142
143 const f64 seconds_per_minute = 60;
144 const f64 seconds_per_hour = 60 * seconds_per_minute;
145 const f64 seconds_per_day = 24 * seconds_per_hour;
146 uword days, hours, minutes, secs, msecs, usecs;
147
148 days = t / seconds_per_day;
149 t -= days * seconds_per_day;
150
151 hours = t / seconds_per_hour;
152 t -= hours * seconds_per_hour;
153
154 minutes = t / seconds_per_minute;
155 t -= minutes * seconds_per_minute;
156
157 secs = t;
158 t -= secs;
159
160 msecs = 1e3 * t;
161
162 usecs = 1e6 * t;
163 usecs = usecs % 1000;
164
165 if (t == 0.)
166 s = format (s, "0");
167 if (days)
168 s = format (s, "%ddays ", days);
169 if (hours)
170 s = format (s, "%dh ", hours);
171 if (minutes)
172 s = format (s, "%dmin ", minutes);
173 if (secs)
174 s = format (s, "%ds ", secs);
175 if (msecs)
176 s = format (s, "%dms ", msecs);
177 if (usecs)
178 s = format (s, "%dus", usecs);
179
180 return (s);
181}
182
183u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400184format_time_interval (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700185{
Dave Barachc3799992016-08-15 11:12:27 -0400186 u8 *fmt = va_arg (*args, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187 f64 t = va_arg (*args, f64);
Dave Barachc3799992016-08-15 11:12:27 -0400188 u8 *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700189
190 const f64 seconds_per_minute = 60;
191 const f64 seconds_per_hour = 60 * seconds_per_minute;
192 const f64 seconds_per_day = 24 * seconds_per_hour;
193 uword days, hours, minutes, secs, msecs, usecs;
Dave Barachc3799992016-08-15 11:12:27 -0400194
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195 days = t / seconds_per_day;
196 t -= days * seconds_per_day;
197
198 hours = t / seconds_per_hour;
199 t -= hours * seconds_per_hour;
200
201 minutes = t / seconds_per_minute;
202 t -= minutes * seconds_per_minute;
203
204 secs = t;
205 t -= secs;
206
Dave Barachc3799992016-08-15 11:12:27 -0400207 msecs = 1e3 * t;
208 usecs = 1e6 * t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209
210 for (f = fmt; *f; f++)
211 {
212 uword what, c;
Dave Barachc3799992016-08-15 11:12:27 -0400213 char *what_fmt = "%d";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214
215 switch (c = *f)
216 {
217 default:
218 vec_add1 (s, c);
219 continue;
220
221 case 'd':
222 what = days;
223 what_fmt = "%d";
224 break;
225 case 'h':
226 what = hours;
227 what_fmt = "%02d";
228 break;
229 case 'm':
230 what = minutes;
231 what_fmt = "%02d";
232 break;
233 case 's':
234 what = secs;
235 what_fmt = "%02d";
236 break;
237 case 'f':
238 what = msecs;
239 what_fmt = "%03d";
240 break;
241 case 'u':
242 what = usecs;
243 what_fmt = "%06d";
244 break;
245 }
246
247 s = format (s, what_fmt, what);
248 }
249
250 return s;
251}
252
Nathan Skrzypczak162ff5e2021-11-09 18:18:21 +0100253/* Format base 10 e.g. 100, 100K, 100M, 100G */
254__clib_export u8 *
255format_base10 (u8 *s, va_list *va)
256{
Pim van Pelta5266c62022-07-19 08:32:22 +0000257 u64 size = va_arg (*va, u64);
Nathan Skrzypczak162ff5e2021-11-09 18:18:21 +0100258
259 if (size < 1000)
260 s = format (s, "%d", size);
261 else if (size < 1000000)
262 s = format (s, "%.2fK", (f64) size / 1000.);
263 else if (size < 1000000000)
264 s = format (s, "%.2fM", (f64) size / 1000000.);
265 else
266 s = format (s, "%.2fG", (f64) size / 1000000000.);
267
268 return s;
269}
270
Ed Warnickecb9cada2015-12-08 15:45:58 -0700271/* Unparse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200272__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400273format_memory_size (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700274{
275 uword size = va_arg (*va, uword);
276 uword l, u, log_u;
277
278 l = size > 0 ? min_log2 (size) : 0;
279 if (l < 10)
280 log_u = 0;
281 else if (l < 20)
282 log_u = 10;
283 else if (l < 30)
284 log_u = 20;
285 else
286 log_u = 30;
287
288 u = (uword) 1 << log_u;
289 if (size & (u - 1))
290 s = format (s, "%.2f", (f64) size / (f64) u);
291 else
292 s = format (s, "%d", size >> log_u);
293
294 if (log_u != 0)
295 s = format (s, "%c", " kmg"[log_u / 10]);
296
297 return s;
298}
299
300/* Parse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200301__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400302unformat_memory_size (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700303{
304 uword amount, shift, c;
Dave Barachc3799992016-08-15 11:12:27 -0400305 uword *result = va_arg (*va, uword *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306
Dave Barachc3799992016-08-15 11:12:27 -0400307 if (!unformat (input, "%wd%_", &amount))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308 return 0;
309
310 c = unformat_get_input (input);
311 switch (c)
312 {
Dave Barachc3799992016-08-15 11:12:27 -0400313 case 'k':
314 case 'K':
315 shift = 10;
316 break;
317 case 'm':
318 case 'M':
319 shift = 20;
320 break;
321 case 'g':
322 case 'G':
323 shift = 30;
324 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700325 default:
326 shift = 0;
327 unformat_put_input (input);
328 break;
329 }
330
331 *result = amount << shift;
332 return 1;
333}
334
Damjan Marionb5095042020-09-11 22:13:46 +0200335/* Unparse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200336__clib_export u8 *
Damjan Marionb5095042020-09-11 22:13:46 +0200337format_log2_page_size (u8 * s, va_list * va)
338{
339 clib_mem_page_sz_t log2_page_sz = va_arg (*va, clib_mem_page_sz_t);
340
341 if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
342 return format (s, "unknown");
343
344 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT)
345 return format (s, "default");
346
347 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE)
348 return format (s, "default-hugepage");
349
350 if (log2_page_sz >= 30)
351 return format (s, "%uG", 1 << (log2_page_sz - 30));
352
353 if (log2_page_sz >= 20)
354 return format (s, "%uM", 1 << (log2_page_sz - 20));
355
356 if (log2_page_sz >= 10)
357 return format (s, "%uK", 1 << (log2_page_sz - 10));
358
359 return format (s, "%u", 1 << log2_page_sz);
360}
361
362/* Parse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200363__clib_export uword
Damjan Marionb5095042020-09-11 22:13:46 +0200364unformat_log2_page_size (unformat_input_t * input, va_list * va)
365{
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100366 uword amount;
Damjan Marionb5095042020-09-11 22:13:46 +0200367 clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
368
Damjan Marionb5095042020-09-11 22:13:46 +0200369 if (unformat (input, "default-hugepage"))
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100370 *result = CLIB_MEM_PAGE_SZ_DEFAULT_HUGE;
371 else if (unformat (input, "default"))
372 *result = CLIB_MEM_PAGE_SZ_DEFAULT;
373 else if (unformat (input, "%wdk", &amount))
374 *result = min_log2 (amount) + 10;
375 else if (unformat (input, "%wdK", &amount))
376 *result = min_log2 (amount) + 10;
377 else if (unformat (input, "%wdm", &amount))
378 *result = min_log2 (amount) + 20;
379 else if (unformat (input, "%wdM", &amount))
380 *result = min_log2 (amount) + 20;
381 else if (unformat (input, "%wdg", &amount))
382 *result = min_log2 (amount) + 30;
383 else if (unformat (input, "%wdG", &amount))
384 *result = min_log2 (amount) + 30;
385 else
386 return 0;
Damjan Marionb5095042020-09-11 22:13:46 +0200387 return 1;
388}
389
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390/* Format c identifier: e.g. a_name -> "a name".
Klement Sekeraea841302018-05-11 12:59:05 +0200391 Works for both vector names and null terminated c strings. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200392__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400393format_c_identifier (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394{
Dave Barachc3799992016-08-15 11:12:27 -0400395 u8 *id = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700396 uword i, l;
397
398 l = ~0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399
400 if (id)
BenoƮt Ganne1bd6f612020-07-16 12:03:35 +0200401 for (i = 0; i < l && id[i] != 0; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402 {
403 u8 c = id[i];
404
405 if (c == '_')
406 c = ' ';
407 vec_add1 (s, c);
408 }
409
410 return s;
411}
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200412
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200413__clib_export u8 *
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200414format_hexdump (u8 * s, va_list * args)
415{
Dave Barachc3799992016-08-15 11:12:27 -0400416 u8 *data = va_arg (*args, u8 *);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200417 uword len = va_arg (*args, uword);
Dave Barachc3799992016-08-15 11:12:27 -0400418 int i, index = 0;
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200419 const int line_len = 16;
Dave Barachc3799992016-08-15 11:12:27 -0400420 u8 *line_hex = 0;
421 u8 *line_str = 0;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200422 u32 indent = format_get_indent (s);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200423
424 if (!len)
425 return s;
426
Dave Barachc3799992016-08-15 11:12:27 -0400427 for (i = 0; i < len; i++)
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200428 {
Dave Barachc3799992016-08-15 11:12:27 -0400429 line_hex = format (line_hex, "%02x ", data[i]);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200430 line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
Dave Barachc3799992016-08-15 11:12:27 -0400431 if (!((i + 1) % line_len))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200432 {
433 s = format (s, "%U%05x: %v[%v]",
434 format_white_space, index ? indent : 0,
435 index, line_hex, line_str);
436 if (i < len - 1)
437 s = format (s, "\n");
438 index = i + 1;
Dave Barachc3799992016-08-15 11:12:27 -0400439 vec_reset_length (line_hex);
440 vec_reset_length (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200441 }
442 }
443
444 while (i++ % line_len)
445 line_hex = format (line_hex, " ");
446
Dave Barachc3799992016-08-15 11:12:27 -0400447 if (vec_len (line_hex))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200448 s = format (s, "%U%05x: %v[%v]",
Damjan Marion1e336632018-02-17 14:05:08 +0100449 format_white_space, index ? indent : 0,
450 index, line_hex, line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200451
Dave Barachc3799992016-08-15 11:12:27 -0400452 vec_free (line_hex);
453 vec_free (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200454
455 return s;
456}
Dave Barachc3799992016-08-15 11:12:27 -0400457
Damjan Marione6387b22021-12-22 21:58:54 +0100458__clib_export u8 *
459format_u64_bitmap (u8 *s, va_list *args)
460{
461 u64 *bitmap = va_arg (*args, u64 *);
462 int n_uword = va_arg (*args, int);
463 u32 indent = format_get_indent (s);
464
465 s = format (s, "%6s", "");
466
467 for (int i = 60; i >= 0; i -= 4)
468 s = format (s, "%5d", i);
469
470 vec_add1 (s, '\n');
471
472 for (int j = n_uword - 1; j >= 0; j--)
473 {
474 s = format (s, "%U0x%04x ", format_white_space, indent, j * 8);
475 for (int i = 63; i >= 0; i--)
476 {
477 vec_add1 (s, (1ULL << i) & bitmap[j] ? '1' : '.');
478 if (i % 4 == 0)
479 vec_add1 (s, ' ');
480 }
481 s = format (s, "0x%016lx", bitmap[j]);
482 if (j)
483 vec_add1 (s, '\n');
484 }
485
486 return s;
487}
488
Dave Barachc3799992016-08-15 11:12:27 -0400489/*
490 * fd.io coding-style-patch-verification: ON
491 *
492 * Local Variables:
493 * eval: (c-set-style "gnu")
494 * End:
495 */