blob: 62d309e2fb0c5dbedeb3d98e40933f27860fa1ee [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. */
Dave Barachc3799992016-08-15 11:12:27 -0400208u8 *
209format_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. */
Dave Barachc3799992016-08-15 11:12:27 -0400237uword
238unformat_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
271/* Format c identifier: e.g. a_name -> "a name".
Klement Sekeraea841302018-05-11 12:59:05 +0200272 Works for both vector names and null terminated c strings. */
Dave Barachc3799992016-08-15 11:12:27 -0400273u8 *
274format_c_identifier (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700275{
Dave Barachc3799992016-08-15 11:12:27 -0400276 u8 *id = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277 uword i, l;
278
279 l = ~0;
280 if (clib_mem_is_vec (id))
281 l = vec_len (id);
282
283 if (id)
BenoƮt Ganne1bd6f612020-07-16 12:03:35 +0200284 for (i = 0; i < l && id[i] != 0; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285 {
286 u8 c = id[i];
287
288 if (c == '_')
289 c = ' ';
290 vec_add1 (s, c);
291 }
292
293 return s;
294}
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200295
296u8 *
297format_hexdump (u8 * s, va_list * args)
298{
Dave Barachc3799992016-08-15 11:12:27 -0400299 u8 *data = va_arg (*args, u8 *);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200300 uword len = va_arg (*args, uword);
Dave Barachc3799992016-08-15 11:12:27 -0400301 int i, index = 0;
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200302 const int line_len = 16;
Dave Barachc3799992016-08-15 11:12:27 -0400303 u8 *line_hex = 0;
304 u8 *line_str = 0;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200305 u32 indent = format_get_indent (s);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200306
307 if (!len)
308 return s;
309
Dave Barachc3799992016-08-15 11:12:27 -0400310 for (i = 0; i < len; i++)
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200311 {
Dave Barachc3799992016-08-15 11:12:27 -0400312 line_hex = format (line_hex, "%02x ", data[i]);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200313 line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
Dave Barachc3799992016-08-15 11:12:27 -0400314 if (!((i + 1) % line_len))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200315 {
316 s = format (s, "%U%05x: %v[%v]",
317 format_white_space, index ? indent : 0,
318 index, line_hex, line_str);
319 if (i < len - 1)
320 s = format (s, "\n");
321 index = i + 1;
Dave Barachc3799992016-08-15 11:12:27 -0400322 vec_reset_length (line_hex);
323 vec_reset_length (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200324 }
325 }
326
327 while (i++ % line_len)
328 line_hex = format (line_hex, " ");
329
Dave Barachc3799992016-08-15 11:12:27 -0400330 if (vec_len (line_hex))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200331 s = format (s, "%U%05x: %v[%v]",
Damjan Marion1e336632018-02-17 14:05:08 +0100332 format_white_space, index ? indent : 0,
333 index, line_hex, line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200334
Dave Barachc3799992016-08-15 11:12:27 -0400335 vec_free (line_hex);
336 vec_free (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200337
338 return s;
339}
Dave Barachc3799992016-08-15 11:12:27 -0400340
341/*
342 * fd.io coding-style-patch-verification: ON
343 *
344 * Local Variables:
345 * eval: (c-set-style "gnu")
346 * End:
347 */