Line data Source code
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 : #include <vppinfra/format.h>
39 : #include <ctype.h>
40 :
41 : /* Format vectors. */
42 : u8 *
43 1518 : format_vec32 (u8 * s, va_list * va)
44 : {
45 1518 : u32 *v = va_arg (*va, u32 *);
46 1518 : char *fmt = va_arg (*va, char *);
47 : uword i;
48 2868 : for (i = 0; i < vec_len (v); i++)
49 : {
50 1350 : if (i > 0)
51 293 : s = format (s, ", ");
52 1350 : s = format (s, fmt, v[i]);
53 : }
54 1518 : return s;
55 : }
56 :
57 : u8 *
58 0 : format_vec_uword (u8 * s, va_list * va)
59 : {
60 0 : uword *v = va_arg (*va, uword *);
61 0 : char *fmt = va_arg (*va, char *);
62 : uword i;
63 0 : for (i = 0; i < vec_len (v); i++)
64 : {
65 0 : if (i > 0)
66 0 : s = format (s, ", ");
67 0 : s = format (s, fmt, v[i]);
68 : }
69 0 : return s;
70 : }
71 :
72 : /* Ascii buffer and length. */
73 : u8 *
74 0 : format_ascii_bytes (u8 * s, va_list * va)
75 : {
76 0 : u8 *v = va_arg (*va, u8 *);
77 0 : uword n_bytes = va_arg (*va, uword);
78 0 : vec_add (s, v, n_bytes);
79 0 : return s;
80 : }
81 :
82 : /* Format hex dump. */
83 : u8 *
84 0 : format_hex_bytes (u8 * s, va_list * va)
85 : {
86 0 : u8 *bytes = va_arg (*va, u8 *);
87 0 : int n_bytes = va_arg (*va, int);
88 : uword i;
89 :
90 : /* Print short or long form depending on byte count. */
91 0 : uword short_form = n_bytes <= 32;
92 0 : u32 indent = format_get_indent (s);
93 :
94 0 : if (n_bytes == 0)
95 0 : return s;
96 :
97 0 : for (i = 0; i < n_bytes; i++)
98 : {
99 0 : if (!short_form && (i % 32) == 0)
100 0 : s = format (s, "%08x: ", i);
101 :
102 0 : s = format (s, "%02x", bytes[i]);
103 :
104 0 : if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
105 0 : s = format (s, "\n%U", format_white_space, indent);
106 : }
107 :
108 0 : return s;
109 : }
110 :
111 : u8 *
112 0 : format_hex_bytes_no_wrap (u8 * s, va_list * va)
113 : {
114 0 : u8 *bytes = va_arg (*va, u8 *);
115 0 : int n_bytes = va_arg (*va, int);
116 : uword i;
117 :
118 0 : if (n_bytes == 0)
119 0 : return s;
120 :
121 0 : for (i = 0; i < n_bytes; i++)
122 0 : s = format (s, "%02x", bytes[i]);
123 :
124 0 : return s;
125 : }
126 :
127 : /* Add variable number of spaces. */
128 : u8 *
129 10007600 : format_white_space (u8 * s, va_list * va)
130 : {
131 10007600 : u32 n = va_arg (*va, u32);
132 47643700 : while (n-- > 0)
133 37636000 : vec_add1 (s, ' ');
134 10007600 : return s;
135 : }
136 :
137 : u8 *
138 0 : format_duration (u8 *s, va_list *args)
139 : {
140 0 : f64 t = va_arg (*args, f64);
141 0 : s = format (s, "");
142 :
143 0 : const f64 seconds_per_minute = 60;
144 0 : const f64 seconds_per_hour = 60 * seconds_per_minute;
145 0 : const f64 seconds_per_day = 24 * seconds_per_hour;
146 : uword days, hours, minutes, secs, msecs, usecs;
147 :
148 0 : days = t / seconds_per_day;
149 0 : t -= days * seconds_per_day;
150 :
151 0 : hours = t / seconds_per_hour;
152 0 : t -= hours * seconds_per_hour;
153 :
154 0 : minutes = t / seconds_per_minute;
155 0 : t -= minutes * seconds_per_minute;
156 :
157 0 : secs = t;
158 0 : t -= secs;
159 :
160 0 : msecs = 1e3 * t;
161 :
162 0 : usecs = 1e6 * t;
163 0 : usecs = usecs % 1000;
164 :
165 0 : if (t == 0.)
166 0 : s = format (s, "0");
167 0 : if (days)
168 0 : s = format (s, "%ddays ", days);
169 0 : if (hours)
170 0 : s = format (s, "%dh ", hours);
171 0 : if (minutes)
172 0 : s = format (s, "%dmin ", minutes);
173 0 : if (secs)
174 0 : s = format (s, "%ds ", secs);
175 0 : if (msecs)
176 0 : s = format (s, "%dms ", msecs);
177 0 : if (usecs)
178 0 : s = format (s, "%dus", usecs);
179 :
180 0 : return (s);
181 : }
182 :
183 : u8 *
184 3836920 : format_time_interval (u8 * s, va_list * args)
185 : {
186 3836920 : u8 *fmt = va_arg (*args, u8 *);
187 3836920 : f64 t = va_arg (*args, f64);
188 : u8 *f;
189 :
190 3836920 : const f64 seconds_per_minute = 60;
191 3836920 : const f64 seconds_per_hour = 60 * seconds_per_minute;
192 3836920 : const f64 seconds_per_day = 24 * seconds_per_hour;
193 : uword days, hours, minutes, secs, msecs, usecs;
194 :
195 3836920 : days = t / seconds_per_day;
196 3836920 : t -= days * seconds_per_day;
197 :
198 3836920 : hours = t / seconds_per_hour;
199 3836920 : t -= hours * seconds_per_hour;
200 :
201 3836920 : minutes = t / seconds_per_minute;
202 3836920 : t -= minutes * seconds_per_minute;
203 :
204 3836920 : secs = t;
205 3836920 : t -= secs;
206 :
207 3836920 : msecs = 1e3 * t;
208 3836920 : usecs = 1e6 * t;
209 :
210 30695400 : for (f = fmt; *f; f++)
211 : {
212 : uword what, c;
213 26858500 : char *what_fmt = "%d";
214 :
215 26858500 : switch (c = *f)
216 : {
217 11510800 : default:
218 11510800 : vec_add1 (s, c);
219 11510800 : continue;
220 :
221 0 : case 'd':
222 0 : what = days;
223 0 : what_fmt = "%d";
224 0 : break;
225 3836920 : case 'h':
226 3836920 : what = hours;
227 3836920 : what_fmt = "%02d";
228 3836920 : break;
229 3836920 : case 'm':
230 3836920 : what = minutes;
231 3836920 : what_fmt = "%02d";
232 3836920 : break;
233 3836920 : case 's':
234 3836920 : what = secs;
235 3836920 : what_fmt = "%02d";
236 3836920 : break;
237 0 : case 'f':
238 0 : what = msecs;
239 0 : what_fmt = "%03d";
240 0 : break;
241 3836920 : case 'u':
242 3836920 : what = usecs;
243 3836920 : what_fmt = "%06d";
244 3836920 : break;
245 : }
246 :
247 15347700 : s = format (s, what_fmt, what);
248 : }
249 :
250 3836920 : return s;
251 : }
252 :
253 : /* Format base 10 e.g. 100, 100K, 100M, 100G */
254 : __clib_export u8 *
255 0 : format_base10 (u8 *s, va_list *va)
256 : {
257 0 : u64 size = va_arg (*va, u64);
258 :
259 0 : if (size < 1000)
260 0 : s = format (s, "%d", size);
261 0 : else if (size < 1000000)
262 0 : s = format (s, "%.2fK", (f64) size / 1000.);
263 0 : else if (size < 1000000000)
264 0 : s = format (s, "%.2fM", (f64) size / 1000000.);
265 : else
266 0 : s = format (s, "%.2fG", (f64) size / 1000000000.);
267 :
268 0 : return s;
269 : }
270 :
271 : /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
272 : __clib_export u8 *
273 46467 : format_memory_size (u8 * s, va_list * va)
274 : {
275 46467 : uword size = va_arg (*va, uword);
276 : uword l, u, log_u;
277 :
278 46467 : l = size > 0 ? min_log2 (size) : 0;
279 46467 : if (l < 10)
280 17045 : log_u = 0;
281 29422 : else if (l < 20)
282 23118 : log_u = 10;
283 6304 : else if (l < 30)
284 6304 : log_u = 20;
285 : else
286 0 : log_u = 30;
287 :
288 46467 : u = (uword) 1 << log_u;
289 46467 : if (size & (u - 1))
290 8593 : s = format (s, "%.2f", (f64) size / (f64) u);
291 : else
292 37874 : s = format (s, "%d", size >> log_u);
293 :
294 46467 : if (log_u != 0)
295 29422 : s = format (s, "%c", " kmg"[log_u / 10]);
296 :
297 46467 : return s;
298 : }
299 :
300 : /* Parse memory size e.g. 100, 100k, 100m, 100g. */
301 : __clib_export uword
302 651 : unformat_memory_size (unformat_input_t * input, va_list * va)
303 : {
304 : uword amount, shift, c;
305 651 : uword *result = va_arg (*va, uword *);
306 :
307 651 : if (!unformat (input, "%wd%_", &amount))
308 0 : return 0;
309 :
310 651 : c = unformat_get_input (input);
311 651 : switch (c)
312 : {
313 0 : case 'k':
314 : case 'K':
315 0 : shift = 10;
316 0 : break;
317 651 : case 'm':
318 : case 'M':
319 651 : shift = 20;
320 651 : break;
321 0 : case 'g':
322 : case 'G':
323 0 : shift = 30;
324 0 : break;
325 0 : default:
326 0 : shift = 0;
327 0 : unformat_put_input (input);
328 0 : break;
329 : }
330 :
331 651 : *result = amount << shift;
332 651 : return 1;
333 : }
334 :
335 : /* Unparse memory page size e.g. 4K, 2M */
336 : __clib_export u8 *
337 841 : format_log2_page_size (u8 * s, va_list * va)
338 : {
339 841 : clib_mem_page_sz_t log2_page_sz = va_arg (*va, clib_mem_page_sz_t);
340 :
341 841 : if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
342 0 : return format (s, "unknown");
343 :
344 841 : if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT)
345 0 : return format (s, "default");
346 :
347 841 : if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE)
348 0 : return format (s, "default-hugepage");
349 :
350 841 : if (log2_page_sz >= 30)
351 0 : return format (s, "%uG", 1 << (log2_page_sz - 30));
352 :
353 841 : if (log2_page_sz >= 20)
354 0 : return format (s, "%uM", 1 << (log2_page_sz - 20));
355 :
356 841 : if (log2_page_sz >= 10)
357 841 : return format (s, "%uK", 1 << (log2_page_sz - 10));
358 :
359 0 : return format (s, "%u", 1 << log2_page_sz);
360 : }
361 :
362 : /* Parse memory page size e.g. 4K, 2M */
363 : __clib_export uword
364 0 : unformat_log2_page_size (unformat_input_t * input, va_list * va)
365 : {
366 : uword amount;
367 0 : clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
368 :
369 0 : if (unformat (input, "default-hugepage"))
370 0 : *result = CLIB_MEM_PAGE_SZ_DEFAULT_HUGE;
371 0 : else if (unformat (input, "default"))
372 0 : *result = CLIB_MEM_PAGE_SZ_DEFAULT;
373 0 : else if (unformat (input, "%wdk", &amount))
374 0 : *result = min_log2 (amount) + 10;
375 0 : else if (unformat (input, "%wdK", &amount))
376 0 : *result = min_log2 (amount) + 10;
377 0 : else if (unformat (input, "%wdm", &amount))
378 0 : *result = min_log2 (amount) + 20;
379 0 : else if (unformat (input, "%wdM", &amount))
380 0 : *result = min_log2 (amount) + 20;
381 0 : else if (unformat (input, "%wdg", &amount))
382 0 : *result = min_log2 (amount) + 30;
383 0 : else if (unformat (input, "%wdG", &amount))
384 0 : *result = min_log2 (amount) + 30;
385 : else
386 0 : return 0;
387 0 : return 1;
388 : }
389 :
390 : /* Format c identifier: e.g. a_name -> "a name".
391 : Works for both vector names and null terminated c strings. */
392 : __clib_export u8 *
393 0 : format_c_identifier (u8 * s, va_list * va)
394 : {
395 0 : u8 *id = va_arg (*va, u8 *);
396 : uword i, l;
397 :
398 0 : l = ~0;
399 :
400 0 : if (id)
401 0 : for (i = 0; i < l && id[i] != 0; i++)
402 : {
403 0 : u8 c = id[i];
404 :
405 0 : if (c == '_')
406 0 : c = ' ';
407 0 : vec_add1 (s, c);
408 : }
409 :
410 0 : return s;
411 : }
412 :
413 : __clib_export u8 *
414 0 : format_hexdump (u8 * s, va_list * args)
415 : {
416 0 : u8 *data = va_arg (*args, u8 *);
417 0 : u32 len = va_arg (*args, u32);
418 0 : int i, index = 0;
419 0 : const int line_len = 16;
420 0 : u8 *line_hex = 0;
421 0 : u8 *line_str = 0;
422 0 : u32 indent = format_get_indent (s);
423 :
424 0 : if (!len)
425 0 : return s;
426 :
427 0 : for (i = 0; i < len; i++)
428 : {
429 0 : line_hex = format (line_hex, "%02x ", data[i]);
430 0 : line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
431 0 : if (!((i + 1) % line_len))
432 : {
433 0 : s = format (s, "%U%05x: %v[%v]",
434 : format_white_space, index ? indent : 0,
435 : index, line_hex, line_str);
436 0 : if (i < len - 1)
437 0 : s = format (s, "\n");
438 0 : index = i + 1;
439 0 : vec_reset_length (line_hex);
440 0 : vec_reset_length (line_str);
441 : }
442 : }
443 :
444 0 : while (i++ % line_len)
445 0 : line_hex = format (line_hex, " ");
446 :
447 0 : if (vec_len (line_hex))
448 0 : s = format (s, "%U%05x: %v[%v]",
449 : format_white_space, index ? indent : 0,
450 : index, line_hex, line_str);
451 :
452 0 : vec_free (line_hex);
453 0 : vec_free (line_str);
454 :
455 0 : return s;
456 : }
457 :
458 : __clib_export u8 *
459 0 : format_hexdump_u16 (u8 *s, va_list *args)
460 : {
461 0 : u16 *data = va_arg (*args, u16 *);
462 0 : u32 len = va_arg (*args, u32);
463 0 : u32 indent = format_get_indent (s);
464 :
465 0 : if (!len)
466 0 : return s;
467 :
468 0 : for (int i = 0; i < len; i++)
469 : {
470 0 : if (i % 8 == 0)
471 : {
472 0 : s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
473 : i ? indent : 0, i * 2);
474 : }
475 0 : s = format (s, " %04lx", data[i]);
476 : }
477 0 : return s;
478 : }
479 :
480 : __clib_export u8 *
481 0 : format_hexdump_u32 (u8 *s, va_list *args)
482 : {
483 0 : u32 *data = va_arg (*args, u32 *);
484 0 : u32 len = va_arg (*args, u32);
485 0 : u32 indent = format_get_indent (s);
486 :
487 0 : if (!len)
488 0 : return s;
489 :
490 0 : for (int i = 0; i < len; i++)
491 : {
492 0 : if (i % 4 == 0)
493 : {
494 0 : s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
495 : i ? indent : 0, i * 4);
496 : }
497 0 : s = format (s, " %08lx", data[i]);
498 : }
499 0 : return s;
500 : }
501 :
502 : __clib_export u8 *
503 0 : format_hexdump_u64 (u8 *s, va_list *args)
504 : {
505 0 : u64 *data = va_arg (*args, u64 *);
506 0 : u32 len = va_arg (*args, u32);
507 0 : u32 indent = format_get_indent (s);
508 :
509 0 : if (!len)
510 0 : return s;
511 :
512 0 : for (int i = 0; i < len; i++)
513 : {
514 0 : if (i % 2 == 0)
515 : {
516 0 : s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
517 : i ? indent : 0, i * 8);
518 : }
519 0 : s = format (s, " %016lx", data[i]);
520 : }
521 0 : return s;
522 : }
523 :
524 : __clib_export u8 *
525 0 : format_uword_bitmap (u8 *s, va_list *args)
526 : {
527 0 : uword *bitmap = va_arg (*args, uword *);
528 0 : int n_uword = va_arg (*args, int);
529 0 : uword indent = format_get_indent (s);
530 :
531 0 : s = format (s, "%6s", "");
532 :
533 0 : for (int i = uword_bits - 4; i >= 0; i -= 4)
534 0 : s = format (s, "%5d", i);
535 :
536 0 : vec_add1 (s, '\n');
537 :
538 0 : for (int j = n_uword - 1; j >= 0; j--)
539 : {
540 0 : s = format (s, "%U0x%04x ", format_white_space, indent,
541 : j * uword_bits / 8);
542 0 : for (int i = uword_bits - 1; i >= 0; i--)
543 : {
544 0 : vec_add1 (s, (1ULL << i) & bitmap[j] ? '1' : '.');
545 0 : if (i % 4 == 0)
546 0 : vec_add1 (s, ' ');
547 : }
548 0 : s = format (s, uword_bits == 64 ? "0x%016lx" : "0x%08lx", bitmap[j]);
549 0 : if (j)
550 0 : vec_add1 (s, '\n');
551 : }
552 :
553 0 : return s;
554 : }
555 :
556 : /*
557 : * fd.io coding-style-patch-verification: ON
558 : *
559 : * Local Variables:
560 : * eval: (c-set-style "gnu")
561 : * End:
562 : */
|