blob: 1616001f9c54bac6ef27fbf3aefd42767771cc44 [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{
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100302 uword amount;
Damjan Marionb5095042020-09-11 22:13:46 +0200303 clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
304
Damjan Marionb5095042020-09-11 22:13:46 +0200305 if (unformat (input, "default-hugepage"))
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100306 *result = CLIB_MEM_PAGE_SZ_DEFAULT_HUGE;
307 else if (unformat (input, "default"))
308 *result = CLIB_MEM_PAGE_SZ_DEFAULT;
309 else if (unformat (input, "%wdk", &amount))
310 *result = min_log2 (amount) + 10;
311 else if (unformat (input, "%wdK", &amount))
312 *result = min_log2 (amount) + 10;
313 else if (unformat (input, "%wdm", &amount))
314 *result = min_log2 (amount) + 20;
315 else if (unformat (input, "%wdM", &amount))
316 *result = min_log2 (amount) + 20;
317 else if (unformat (input, "%wdg", &amount))
318 *result = min_log2 (amount) + 30;
319 else if (unformat (input, "%wdG", &amount))
320 *result = min_log2 (amount) + 30;
321 else
322 return 0;
Damjan Marionb5095042020-09-11 22:13:46 +0200323 return 1;
324}
325
Ed Warnickecb9cada2015-12-08 15:45:58 -0700326/* Format c identifier: e.g. a_name -> "a name".
Klement Sekeraea841302018-05-11 12:59:05 +0200327 Works for both vector names and null terminated c strings. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200328__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400329format_c_identifier (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700330{
Dave Barachc3799992016-08-15 11:12:27 -0400331 u8 *id = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700332 uword i, l;
333
334 l = ~0;
335 if (clib_mem_is_vec (id))
336 l = vec_len (id);
337
338 if (id)
BenoƮt Ganne1bd6f612020-07-16 12:03:35 +0200339 for (i = 0; i < l && id[i] != 0; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700340 {
341 u8 c = id[i];
342
343 if (c == '_')
344 c = ' ';
345 vec_add1 (s, c);
346 }
347
348 return s;
349}
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200350
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200351__clib_export u8 *
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200352format_hexdump (u8 * s, va_list * args)
353{
Dave Barachc3799992016-08-15 11:12:27 -0400354 u8 *data = va_arg (*args, u8 *);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200355 uword len = va_arg (*args, uword);
Dave Barachc3799992016-08-15 11:12:27 -0400356 int i, index = 0;
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200357 const int line_len = 16;
Dave Barachc3799992016-08-15 11:12:27 -0400358 u8 *line_hex = 0;
359 u8 *line_str = 0;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200360 u32 indent = format_get_indent (s);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200361
362 if (!len)
363 return s;
364
Dave Barachc3799992016-08-15 11:12:27 -0400365 for (i = 0; i < len; i++)
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200366 {
Dave Barachc3799992016-08-15 11:12:27 -0400367 line_hex = format (line_hex, "%02x ", data[i]);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200368 line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
Dave Barachc3799992016-08-15 11:12:27 -0400369 if (!((i + 1) % line_len))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200370 {
371 s = format (s, "%U%05x: %v[%v]",
372 format_white_space, index ? indent : 0,
373 index, line_hex, line_str);
374 if (i < len - 1)
375 s = format (s, "\n");
376 index = i + 1;
Dave Barachc3799992016-08-15 11:12:27 -0400377 vec_reset_length (line_hex);
378 vec_reset_length (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200379 }
380 }
381
382 while (i++ % line_len)
383 line_hex = format (line_hex, " ");
384
Dave Barachc3799992016-08-15 11:12:27 -0400385 if (vec_len (line_hex))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200386 s = format (s, "%U%05x: %v[%v]",
Damjan Marion1e336632018-02-17 14:05:08 +0100387 format_white_space, index ? indent : 0,
388 index, line_hex, line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200389
Dave Barachc3799992016-08-15 11:12:27 -0400390 vec_free (line_hex);
391 vec_free (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200392
393 return s;
394}
Dave Barachc3799992016-08-15 11:12:27 -0400395
396/*
397 * fd.io coding-style-patch-verification: ON
398 *
399 * Local Variables:
400 * eval: (c-set-style "gnu")
401 * End:
402 */