ipsec: IPSec protection for multi-point tunnel interfaces
[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_time_interval (u8 * s, va_list * args)
139 {
140   u8 *fmt = va_arg (*args, u8 *);
141   f64 t = va_arg (*args, f64);
142   u8 *f;
143
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;
148
149   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
161   msecs = 1e3 * t;
162   usecs = 1e6 * t;
163
164   for (f = fmt; *f; f++)
165     {
166       uword what, c;
167       char *what_fmt = "%d";
168
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. */
208 u8 *
209 format_memory_size (u8 * s, va_list * va)
210 {
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. */
237 uword
238 unformat_memory_size (unformat_input_t * input, va_list * va)
239 {
240   uword amount, shift, c;
241   uword *result = va_arg (*va, uword *);
242
243   if (!unformat (input, "%wd%_", &amount))
244     return 0;
245
246   c = unformat_get_input (input);
247   switch (c)
248     {
249     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;
261     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".
272    Works for both vector names and null terminated c strings. */
273 u8 *
274 format_c_identifier (u8 * s, va_list * va)
275 {
276   u8 *id = va_arg (*va, u8 *);
277   uword i, l;
278
279   l = ~0;
280   if (clib_mem_is_vec (id))
281     l = vec_len (id);
282
283   if (id)
284     for (i = 0; id[i] != 0 && i < l; i++)
285       {
286         u8 c = id[i];
287
288         if (c == '_')
289           c = ' ';
290         vec_add1 (s, c);
291       }
292
293   return s;
294 }
295
296 u8 *
297 format_hexdump (u8 * s, va_list * args)
298 {
299   u8 *data = va_arg (*args, u8 *);
300   uword len = va_arg (*args, uword);
301   int i, index = 0;
302   const int line_len = 16;
303   u8 *line_hex = 0;
304   u8 *line_str = 0;
305   u32 indent = format_get_indent (s);
306
307   if (!len)
308     return s;
309
310   for (i = 0; i < len; i++)
311     {
312       line_hex = format (line_hex, "%02x ", data[i]);
313       line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
314       if (!((i + 1) % line_len))
315         {
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;
322           vec_reset_length (line_hex);
323           vec_reset_length (line_str);
324         }
325     }
326
327   while (i++ % line_len)
328     line_hex = format (line_hex, "   ");
329
330   if (vec_len (line_hex))
331     s = format (s, "%U%05x: %v[%v]",
332                 format_white_space, index ? indent : 0,
333                 index, line_hex, line_str);
334
335   vec_free (line_hex);
336   vec_free (line_str);
337
338   return s;
339 }
340
341 /*
342  * fd.io coding-style-patch-verification: ON
343  *
344  * Local Variables:
345  * eval: (c-set-style "gnu")
346  * End:
347  */