blob: 1667c93fd88789eff8abdc3c2dcdd19fb69f50cd [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
207/* Unparse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200208__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400209format_memory_size (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210{
211 uword size = va_arg (*va, uword);
212 uword l, u, log_u;
213
214 l = size > 0 ? min_log2 (size) : 0;
215 if (l < 10)
216 log_u = 0;
217 else if (l < 20)
218 log_u = 10;
219 else if (l < 30)
220 log_u = 20;
221 else
222 log_u = 30;
223
224 u = (uword) 1 << log_u;
225 if (size & (u - 1))
226 s = format (s, "%.2f", (f64) size / (f64) u);
227 else
228 s = format (s, "%d", size >> log_u);
229
230 if (log_u != 0)
231 s = format (s, "%c", " kmg"[log_u / 10]);
232
233 return s;
234}
235
236/* Parse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200237__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400238unformat_memory_size (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700239{
240 uword amount, shift, c;
Dave Barachc3799992016-08-15 11:12:27 -0400241 uword *result = va_arg (*va, uword *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700242
Dave Barachc3799992016-08-15 11:12:27 -0400243 if (!unformat (input, "%wd%_", &amount))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244 return 0;
245
246 c = unformat_get_input (input);
247 switch (c)
248 {
Dave Barachc3799992016-08-15 11:12:27 -0400249 case 'k':
250 case 'K':
251 shift = 10;
252 break;
253 case 'm':
254 case 'M':
255 shift = 20;
256 break;
257 case 'g':
258 case 'G':
259 shift = 30;
260 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261 default:
262 shift = 0;
263 unformat_put_input (input);
264 break;
265 }
266
267 *result = amount << shift;
268 return 1;
269}
270
Damjan Marionb5095042020-09-11 22:13:46 +0200271/* Unparse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200272__clib_export u8 *
Damjan Marionb5095042020-09-11 22:13:46 +0200273format_log2_page_size (u8 * s, va_list * va)
274{
275 clib_mem_page_sz_t log2_page_sz = va_arg (*va, clib_mem_page_sz_t);
276
277 if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
278 return format (s, "unknown");
279
280 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT)
281 return format (s, "default");
282
283 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE)
284 return format (s, "default-hugepage");
285
286 if (log2_page_sz >= 30)
287 return format (s, "%uG", 1 << (log2_page_sz - 30));
288
289 if (log2_page_sz >= 20)
290 return format (s, "%uM", 1 << (log2_page_sz - 20));
291
292 if (log2_page_sz >= 10)
293 return format (s, "%uK", 1 << (log2_page_sz - 10));
294
295 return format (s, "%u", 1 << log2_page_sz);
296}
297
298/* Parse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200299__clib_export uword
Damjan Marionb5095042020-09-11 22:13:46 +0200300unformat_log2_page_size (unformat_input_t * input, va_list * va)
301{
302 uword amount, shift, c;
303 clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
304
305 if (unformat (input, "default"))
306 return CLIB_MEM_PAGE_SZ_DEFAULT;
307
308 if (unformat (input, "default-hugepage"))
309 return CLIB_MEM_PAGE_SZ_DEFAULT_HUGE;
310
311 if (!unformat (input, "%wd%_", &amount))
312 return CLIB_MEM_PAGE_SZ_UNKNOWN;
313
314 c = unformat_get_input (input);
315 switch (c)
316 {
317 case 'k':
318 case 'K':
319 shift = 10;
320 break;
321 case 'm':
322 case 'M':
323 shift = 20;
324 break;
325 case 'g':
326 case 'G':
327 shift = 30;
328 break;
329 default:
330 shift = 0;
331 unformat_put_input (input);
332 break;
333 }
334
335 *result = min_log2 (amount) + shift;
336 return 1;
337}
338
Ed Warnickecb9cada2015-12-08 15:45:58 -0700339/* Format c identifier: e.g. a_name -> "a name".
Klement Sekeraea841302018-05-11 12:59:05 +0200340 Works for both vector names and null terminated c strings. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200341__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400342format_c_identifier (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343{
Dave Barachc3799992016-08-15 11:12:27 -0400344 u8 *id = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700345 uword i, l;
346
347 l = ~0;
348 if (clib_mem_is_vec (id))
349 l = vec_len (id);
350
351 if (id)
BenoƮt Ganne1bd6f612020-07-16 12:03:35 +0200352 for (i = 0; i < l && id[i] != 0; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353 {
354 u8 c = id[i];
355
356 if (c == '_')
357 c = ' ';
358 vec_add1 (s, c);
359 }
360
361 return s;
362}
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200363
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200364__clib_export u8 *
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200365format_hexdump (u8 * s, va_list * args)
366{
Dave Barachc3799992016-08-15 11:12:27 -0400367 u8 *data = va_arg (*args, u8 *);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200368 uword len = va_arg (*args, uword);
Dave Barachc3799992016-08-15 11:12:27 -0400369 int i, index = 0;
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200370 const int line_len = 16;
Dave Barachc3799992016-08-15 11:12:27 -0400371 u8 *line_hex = 0;
372 u8 *line_str = 0;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200373 u32 indent = format_get_indent (s);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200374
375 if (!len)
376 return s;
377
Dave Barachc3799992016-08-15 11:12:27 -0400378 for (i = 0; i < len; i++)
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200379 {
Dave Barachc3799992016-08-15 11:12:27 -0400380 line_hex = format (line_hex, "%02x ", data[i]);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200381 line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
Dave Barachc3799992016-08-15 11:12:27 -0400382 if (!((i + 1) % line_len))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200383 {
384 s = format (s, "%U%05x: %v[%v]",
385 format_white_space, index ? indent : 0,
386 index, line_hex, line_str);
387 if (i < len - 1)
388 s = format (s, "\n");
389 index = i + 1;
Dave Barachc3799992016-08-15 11:12:27 -0400390 vec_reset_length (line_hex);
391 vec_reset_length (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200392 }
393 }
394
395 while (i++ % line_len)
396 line_hex = format (line_hex, " ");
397
Dave Barachc3799992016-08-15 11:12:27 -0400398 if (vec_len (line_hex))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200399 s = format (s, "%U%05x: %v[%v]",
Damjan Marion1e336632018-02-17 14:05:08 +0100400 format_white_space, index ? indent : 0,
401 index, line_hex, line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200402
Dave Barachc3799992016-08-15 11:12:27 -0400403 vec_free (line_hex);
404 vec_free (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200405
406 return s;
407}
Dave Barachc3799992016-08-15 11:12:27 -0400408
409/*
410 * fd.io coding-style-patch-verification: ON
411 *
412 * Local Variables:
413 * eval: (c-set-style "gnu")
414 * End:
415 */