Initial commit of vpp code.
[vpp.git] / vppinfra / 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
40 /* Format vectors. */
41 u8 * format_vec32 (u8 * s, va_list * va)
42 {
43   u32 * v = va_arg (*va, u32 *);
44   char * fmt = va_arg (*va, char *);
45   uword i;
46   for (i = 0; i < vec_len (v); i++)
47     {
48       if (i > 0)
49         s = format (s, ", ");
50       s = format (s, fmt, v[i]);
51     }
52   return s;
53 }
54
55 u8 * format_vec_uword (u8 * s, va_list * va)
56 {
57   uword * v = va_arg (*va, uword *);
58   char * fmt = va_arg (*va, char *);
59   uword i;
60   for (i = 0; i < vec_len (v); i++)
61     {
62       if (i > 0)
63         s = format (s, ", ");
64       s = format (s, fmt, v[i]);
65     }
66   return s;
67 }
68
69 /* Ascii buffer and length. */
70 u8 * format_ascii_bytes (u8 * s, va_list * va)
71 {
72   u8 * v = va_arg (*va, u8 *);
73   uword n_bytes = va_arg (*va, uword);
74   vec_add (s, v, n_bytes);
75   return s;
76 }
77
78 /* Format hex dump. */
79 u8 * format_hex_bytes (u8 * s, va_list * va)
80 {
81   u8 * bytes = va_arg (*va, u8 *);
82   int n_bytes = va_arg (*va, int);
83   uword i;
84
85   /* Print short or long form depending on byte count. */
86   uword short_form = n_bytes <= 32;
87   uword indent = format_get_indent (s);
88
89   if (n_bytes == 0)
90     return s;
91
92   for (i = 0; i < n_bytes; i++)
93     {
94       if (! short_form && (i % 32) == 0)
95         s = format (s, "%08x: ", i);
96
97       s = format (s, "%02x", bytes[i]);
98
99       if (! short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
100         s = format (s, "\n%U", format_white_space, indent);
101     }
102
103   return s;
104 }
105
106 /* Add variable number of spaces. */
107 u8 * format_white_space (u8 * s, va_list * va)
108 {
109   uword n = va_arg (*va, uword);
110   while (n-- > 0)
111     vec_add1 (s, ' ');
112   return s;
113 }
114
115 u8 * format_time_interval (u8 * s, va_list * args)
116 {
117   u8 * fmt = va_arg (*args, u8 *);
118   f64 t = va_arg (*args, f64);
119   u8 * f;
120
121   const f64 seconds_per_minute = 60;
122   const f64 seconds_per_hour = 60 * seconds_per_minute;
123   const f64 seconds_per_day = 24 * seconds_per_hour;
124   uword days, hours, minutes, secs, msecs, usecs;
125   
126   days = t / seconds_per_day;
127   t -= days * seconds_per_day;
128
129   hours = t / seconds_per_hour;
130   t -= hours * seconds_per_hour;
131
132   minutes = t / seconds_per_minute;
133   t -= minutes * seconds_per_minute;
134
135   secs = t;
136   t -= secs;
137
138   msecs = 1e3*t;
139   usecs = 1e6*t;
140
141   for (f = fmt; *f; f++)
142     {
143       uword what, c;
144       char * what_fmt = "%d";
145
146       switch (c = *f)
147         {
148         default:
149           vec_add1 (s, c);
150           continue;
151
152         case 'd':
153           what = days;
154           what_fmt = "%d";
155           break;
156         case 'h':
157           what = hours;
158           what_fmt = "%02d";
159           break;
160         case 'm':
161           what = minutes;
162           what_fmt = "%02d";
163           break;
164         case 's':
165           what = secs;
166           what_fmt = "%02d";
167           break;
168         case 'f':
169           what = msecs;
170           what_fmt = "%03d";
171           break;
172         case 'u':
173           what = usecs;
174           what_fmt = "%06d";
175           break;
176         }
177
178       s = format (s, what_fmt, what);
179     }
180
181   return s;
182 }
183
184 /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
185 u8 * format_memory_size (u8 * s, va_list * va)
186 {
187   uword size = va_arg (*va, uword);
188   uword l, u, log_u;
189
190   l = size > 0 ? min_log2 (size) : 0;
191   if (l < 10)
192     log_u = 0;
193   else if (l < 20)
194     log_u = 10;
195   else if (l < 30)
196     log_u = 20;
197   else
198     log_u = 30;
199
200   u = (uword) 1 << log_u;
201   if (size & (u - 1))
202     s = format (s, "%.2f", (f64) size / (f64) u);
203   else
204     s = format (s, "%d", size >> log_u);
205
206   if (log_u != 0)
207     s = format (s, "%c", " kmg"[log_u / 10]);
208
209   return s;
210 }
211
212 /* Parse memory size e.g. 100, 100k, 100m, 100g. */
213 uword unformat_memory_size (unformat_input_t * input, va_list * va)
214 {
215   uword amount, shift, c;
216   uword * result = va_arg (*va, uword *);
217
218   if (! unformat (input, "%wd%_", &amount))
219     return 0;
220
221   c = unformat_get_input (input);
222   switch (c)
223     {
224     case 'k': case 'K': shift = 10; break;
225     case 'm': case 'M': shift = 20; break;
226     case 'g': case 'G': shift = 30; break;
227     default:
228       shift = 0;
229       unformat_put_input (input);
230       break;
231     }
232
233   *result = amount << shift;
234   return 1;
235 }
236
237 /* Format c identifier: e.g. a_name -> "a name".
238    Words for both vector names and null terminated c strings. */
239 u8 * format_c_identifier (u8 * s, va_list * va)
240 {
241   u8 * id = va_arg (*va, u8 *);
242   uword i, l;
243
244   l = ~0;
245   if (clib_mem_is_vec (id))
246     l = vec_len (id);
247
248   if (id)
249     for (i = 0; id[i] != 0 && i < l; i++)
250       {
251         u8 c = id[i];
252
253         if (c == '_')
254           c = ' ';
255         vec_add1 (s, c);
256       }
257
258   return s;
259 }