http: ignore http_proxy env in tests
[vpp.git] / src / vppinfra / std-formats.c
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 format_vec32 (u8 * s, va_list * va)
44 {
45   u32 *v = va_arg (*va, u32 *);
46   char *fmt = va_arg (*va, char *);
47   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
57 u8 *
58 format_vec_uword (u8 * s, va_list * va)
59 {
60   uword *v = va_arg (*va, uword *);
61   char *fmt = va_arg (*va, char *);
62   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. */
73 u8 *
74 format_ascii_bytes (u8 * s, va_list * va)
75 {
76   u8 *v = va_arg (*va, u8 *);
77   uword n_bytes = va_arg (*va, uword);
78   vec_add (s, v, n_bytes);
79   return s;
80 }
81
82 /* Format hex dump. */
83 u8 *
84 format_hex_bytes (u8 * s, va_list * va)
85 {
86   u8 *bytes = va_arg (*va, u8 *);
87   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;
92   u32 indent = format_get_indent (s);
93
94   if (n_bytes == 0)
95     return s;
96
97   for (i = 0; i < n_bytes; i++)
98     {
99       if (!short_form && (i % 32) == 0)
100         s = format (s, "%08x: ", i);
101
102       s = format (s, "%02x", bytes[i]);
103
104       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
105         s = format (s, "\n%U", format_white_space, indent);
106     }
107
108   return s;
109 }
110
111 u8 *
112 format_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
127 /* Add variable number of spaces. */
128 u8 *
129 format_white_space (u8 * s, va_list * va)
130 {
131   u32 n = va_arg (*va, u32);
132   while (n-- > 0)
133     vec_add1 (s, ' ');
134   return s;
135 }
136
137 u8 *
138 format_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
183 u8 *
184 format_time_interval (u8 * s, va_list * args)
185 {
186   u8 *fmt = va_arg (*args, u8 *);
187   f64 t = va_arg (*args, f64);
188   u8 *f;
189
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;
194
195   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
207   msecs = 1e3 * t;
208   usecs = 1e6 * t;
209
210   for (f = fmt; *f; f++)
211     {
212       uword what, c;
213       char *what_fmt = "%d";
214
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
253 /* Format base 10 e.g. 100, 100K, 100M, 100G */
254 __clib_export u8 *
255 format_base10 (u8 *s, va_list *va)
256 {
257   u64 size = va_arg (*va, u64);
258
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
271 /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
272 __clib_export u8 *
273 format_memory_size (u8 * s, va_list * va)
274 {
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. */
301 __clib_export uword
302 unformat_memory_size (unformat_input_t * input, va_list * va)
303 {
304   uword amount, shift, c;
305   uword *result = va_arg (*va, uword *);
306
307   if (!unformat (input, "%wd%_", &amount))
308     return 0;
309
310   c = unformat_get_input (input);
311   switch (c)
312     {
313     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;
325     default:
326       shift = 0;
327       unformat_put_input (input);
328       break;
329     }
330
331   *result = amount << shift;
332   return 1;
333 }
334
335 /* Unparse memory page size e.g. 4K, 2M */
336 __clib_export u8 *
337 format_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 */
363 __clib_export uword
364 unformat_log2_page_size (unformat_input_t * input, va_list * va)
365 {
366   uword amount;
367   clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
368
369   if (unformat (input, "default-hugepage"))
370     *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;
387   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 format_c_identifier (u8 * s, va_list * va)
394 {
395   u8 *id = va_arg (*va, u8 *);
396   uword i, l;
397
398   l = ~0;
399
400   if (id)
401     for (i = 0; i < l && id[i] != 0; i++)
402       {
403         u8 c = id[i];
404
405         if (c == '_')
406           c = ' ';
407         vec_add1 (s, c);
408       }
409
410   return s;
411 }
412
413 __clib_export u8 *
414 format_hexdump (u8 * s, va_list * args)
415 {
416   u8 *data = va_arg (*args, u8 *);
417   u32 len = va_arg (*args, u32);
418   int i, index = 0;
419   const int line_len = 16;
420   u8 *line_hex = 0;
421   u8 *line_str = 0;
422   u32 indent = format_get_indent (s);
423
424   if (!len)
425     return s;
426
427   for (i = 0; i < len; i++)
428     {
429       line_hex = format (line_hex, "%02x ", data[i]);
430       line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
431       if (!((i + 1) % line_len))
432         {
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;
439           vec_reset_length (line_hex);
440           vec_reset_length (line_str);
441         }
442     }
443
444   while (i++ % line_len)
445     line_hex = format (line_hex, "   ");
446
447   if (vec_len (line_hex))
448     s = format (s, "%U%05x: %v[%v]",
449                 format_white_space, index ? indent : 0,
450                 index, line_hex, line_str);
451
452   vec_free (line_hex);
453   vec_free (line_str);
454
455   return s;
456 }
457
458 __clib_export u8 *
459 format_hexdump_u16 (u8 *s, va_list *args)
460 {
461   u16 *data = va_arg (*args, u16 *);
462   u32 len = va_arg (*args, u32);
463   u32 indent = format_get_indent (s);
464
465   if (!len)
466     return s;
467
468   for (int i = 0; i < len; i++)
469     {
470       if (i % 8 == 0)
471         {
472           s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
473                       i ? indent : 0, i * 2);
474         }
475       s = format (s, " %04lx", data[i]);
476     }
477   return s;
478 }
479
480 __clib_export u8 *
481 format_hexdump_u32 (u8 *s, va_list *args)
482 {
483   u32 *data = va_arg (*args, u32 *);
484   u32 len = va_arg (*args, u32);
485   u32 indent = format_get_indent (s);
486
487   if (!len)
488     return s;
489
490   for (int i = 0; i < len; i++)
491     {
492       if (i % 4 == 0)
493         {
494           s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
495                       i ? indent : 0, i * 4);
496         }
497       s = format (s, " %08lx", data[i]);
498     }
499   return s;
500 }
501
502 __clib_export u8 *
503 format_hexdump_u64 (u8 *s, va_list *args)
504 {
505   u64 *data = va_arg (*args, u64 *);
506   u32 len = va_arg (*args, u32);
507   u32 indent = format_get_indent (s);
508
509   if (!len)
510     return s;
511
512   for (int i = 0; i < len; i++)
513     {
514       if (i % 2 == 0)
515         {
516           s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
517                       i ? indent : 0, i * 8);
518         }
519       s = format (s, " %016lx", data[i]);
520     }
521   return s;
522 }
523
524 __clib_export u8 *
525 format_uword_bitmap (u8 *s, va_list *args)
526 {
527   uword *bitmap = va_arg (*args, uword *);
528   int n_uword = va_arg (*args, int);
529   uword indent = format_get_indent (s);
530
531   s = format (s, "%6s", "");
532
533   for (int i = uword_bits - 4; i >= 0; i -= 4)
534     s = format (s, "%5d", i);
535
536   vec_add1 (s, '\n');
537
538   for (int j = n_uword - 1; j >= 0; j--)
539     {
540       s = format (s, "%U0x%04x ", format_white_space, indent,
541                   j * uword_bits / 8);
542       for (int i = uword_bits - 1; i >= 0; i--)
543         {
544           vec_add1 (s, (1ULL << i) & bitmap[j] ? '1' : '.');
545           if (i % 4 == 0)
546             vec_add1 (s, ' ');
547         }
548       s = format (s, uword_bits == 64 ? "0x%016lx" : "0x%08lx", bitmap[j]);
549       if (j)
550         vec_add1 (s, '\n');
551     }
552
553   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  */