cf5e1f6dccebd585b0c25d372f9f4cad8309f6b5
[vpp.git] / src / vppinfra / format.h
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 #ifndef included_format_h
39 #define included_format_h
40
41 #include <stdarg.h>
42
43 #include <vppinfra/clib.h>      /* for CLIB_UNIX, etc. */
44 #include <vppinfra/vec.h>
45 #include <vppinfra/error.h>     /* for ASSERT */
46 #include <vppinfra/string.h>
47
48 typedef u8 *(format_function_t) (u8 * s, va_list * args);
49
50 u8 *va_format (u8 * s, const char *format, va_list * args);
51 u8 *format (u8 * s, const char *format, ...);
52
53 #ifdef CLIB_UNIX
54
55 #include <stdio.h>
56
57 #else /* ! CLIB_UNIX */
58
59 /* We're not Unix and have not stdio.h */
60 #define FILE void
61 #define stdin ((FILE *) 0)
62 #define stdout ((FILE *) 1)
63 #define stderr ((FILE *) 2)
64
65 #endif
66
67 word va_fformat (FILE * f, char *fmt, va_list * va);
68 word fformat (FILE * f, char *fmt, ...);
69 word fdformat (int fd, char *fmt, ...);
70
71 always_inline u32
72 format_get_indent (u8 * s)
73 {
74   u32 indent = 0;
75   u8 *nl;
76
77   if (!s)
78     return indent;
79
80   nl = vec_end (s) - 1;
81   while (nl >= s)
82     {
83       if (*nl-- == '\n')
84         break;
85       indent++;
86     }
87   return indent;
88 }
89
90 #define _(f) __clib_export u8 * f (u8 * s, va_list * va)
91
92 /* Standard user-defined formats. */
93 _(format_vec32);
94 _(format_vec_uword);
95 _(format_ascii_bytes);
96 _(format_hex_bytes);
97 _(format_hex_bytes_no_wrap);
98 _(format_white_space);
99 _(format_f64);
100 _(format_time_interval);
101 _ (format_duration);
102
103 #ifdef CLIB_UNIX
104 /* Unix specific formats. */
105 _(format_address_family);
106 _(format_network_address);
107 _(format_network_protocol);
108 _(format_network_port);
109 _(format_sockaddr);
110 _(format_timeval);
111 _(format_time_float);
112 _(format_signal);
113 _(format_ucontext_pc);
114 #endif
115
116 #undef _
117
118 /* Unformat. */
119
120 typedef struct _unformat_input_t
121 {
122   /* Input buffer (vector). */
123   u8 *buffer;
124
125   /* Current index in input buffer. */
126   uword index;
127
128   /* Vector of buffer marks.  Used to delineate pieces of the buffer
129      for error reporting and for parse recovery. */
130   uword *buffer_marks;
131
132   /* User's function to fill the buffer when its empty
133      (and argument). */
134     uword (*fill_buffer) (struct _unformat_input_t * i);
135
136     /* User's function to be called on input_free */
137     void (*free) (struct _unformat_input_t *i);
138
139     /* Return values for fill buffer function which indicate whether not
140        input has been exhausted. */
141 #define UNFORMAT_END_OF_INPUT (~0)
142 #define UNFORMAT_MORE_INPUT   0
143
144   /* User controlled argument to fill buffer function. */
145   void *fill_buffer_arg;
146 } unformat_input_t;
147
148 always_inline void
149 unformat_init (unformat_input_t * i,
150                uword (*fill_buffer) (unformat_input_t *),
151                void *fill_buffer_arg)
152 {
153   clib_memset (i, 0, sizeof (i[0]));
154   i->fill_buffer = fill_buffer;
155   i->fill_buffer_arg = fill_buffer_arg;
156 }
157
158 always_inline void
159 unformat_free (unformat_input_t * i)
160 {
161   if (i->free)
162     i->free (i);
163   vec_free (i->buffer);
164   vec_free (i->buffer_marks);
165   clib_memset (i, 0, sizeof (i[0]));
166 }
167
168 always_inline uword
169 unformat_check_input (unformat_input_t * i)
170 {
171   /* Low level fill input function. */
172   extern uword _unformat_fill_input (unformat_input_t * i);
173
174   if (i->index >= vec_len (i->buffer) && i->index != UNFORMAT_END_OF_INPUT)
175     _unformat_fill_input (i);
176
177   return i->index;
178 }
179
180 /* Return true if input is exhausted */
181 always_inline uword
182 unformat_is_eof (unformat_input_t * input)
183 {
184   return unformat_check_input (input) == UNFORMAT_END_OF_INPUT;
185 }
186
187 /* Return next element in input vector,
188    possibly calling fill input to get more. */
189 always_inline uword
190 unformat_get_input (unformat_input_t * input)
191 {
192   uword i = unformat_check_input (input);
193   if (i < vec_len (input->buffer))
194     {
195       input->index = i + 1;
196       i = input->buffer[i];
197     }
198   return i;
199 }
200
201 /* Back up input pointer by one. */
202 always_inline void
203 unformat_put_input (unformat_input_t * input)
204 {
205   input->index -= 1;
206 }
207
208 always_inline uword
209 is_white_space (uword c)
210 {
211   switch (c)
212     {
213     case ' ':
214     case '\t':
215     case '\n':
216     case '\r':
217       return 1;
218
219     default:
220       return 0;
221     }
222 }
223
224 /* Peek current input character without advancing. */
225 always_inline uword
226 unformat_peek_input (unformat_input_t * input)
227 {
228   uword c = unformat_get_input (input);
229   if (c != UNFORMAT_END_OF_INPUT)
230     unformat_put_input (input);
231   return c;
232 }
233
234 /* Skip current input line. */
235 always_inline void
236 unformat_skip_line (unformat_input_t * i)
237 {
238   uword c;
239
240   while ((c = unformat_get_input (i)) != UNFORMAT_END_OF_INPUT && c != '\n')
241     ;
242 }
243
244 uword unformat_skip_white_space (unformat_input_t * input);
245
246 /* Unformat function. */
247 typedef uword (unformat_function_t) (unformat_input_t * input,
248                                      va_list * args);
249
250 /* External functions. */
251
252 /* General unformatting function with programmable input stream. */
253 uword unformat (unformat_input_t * i, const char *fmt, ...);
254
255 /* Call user defined parse function.
256    unformat_user (i, f, ...) is equivalent to unformat (i, "%U", f, ...) */
257 uword unformat_user (unformat_input_t * input, unformat_function_t * func,
258                      ...);
259
260 /* Alternate version which allows for extensions. */
261 uword va_unformat (unformat_input_t * i, const char *fmt, va_list * args);
262
263 /* Setup for unformat of Unix style command line. */
264 void unformat_init_command_line (unformat_input_t * input, char *argv[]);
265
266 /* Setup for unformat of given string. */
267 void unformat_init_string (unformat_input_t *input, const char *string,
268                            int string_len);
269
270 always_inline void
271 unformat_init_cstring (unformat_input_t * input, char *string)
272 {
273   unformat_init_string (input, string, strlen (string));
274 }
275
276 /* Setup for unformat of given vector string; vector will be freed by unformat_string. */
277 void unformat_init_vector (unformat_input_t * input, u8 * vector_string);
278
279 /* Format function for unformat input usable when an unformat error
280    has occurred. */
281 u8 *format_unformat_error (u8 * s, va_list * va);
282
283 #define unformat_parse_error(input)                                             \
284   clib_error_return (0, "parse error `%U'", format_unformat_error, input)
285
286 /* Print all input: not just error context. */
287 u8 *format_unformat_input (u8 * s, va_list * va);
288
289 /* Unformat (parse) function which reads a %s string and converts it
290    to and unformat_input_t. */
291 unformat_function_t unformat_input;
292
293 /* Parse a line ending with \n and return it. */
294 unformat_function_t unformat_line;
295
296 /* Parse a line ending with \n and return it as an unformat_input_t. */
297 unformat_function_t unformat_line_input;
298
299 /* Parse a token containing given set of characters. */
300 unformat_function_t unformat_token;
301
302 /* Parses a hexstring into a vector of bytes. */
303 unformat_function_t unformat_hex_string;
304
305 /* Returns non-zero match if input is exhausted.
306    Useful to ensure that the entire input matches with no trailing junk. */
307 unformat_function_t unformat_eof;
308
309 /* Parse memory size e.g. 100, 100k, 100m, 100g. */
310 unformat_function_t unformat_memory_size;
311
312 /* Unformat C string array, takes array length as 2nd argument */
313 unformat_function_t unformat_c_string_array;
314
315 /* Format base 10 e.g. 100, 100K, 100M, 100G */
316 u8 *format_base10 (u8 *s, va_list *va);
317
318 /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
319 u8 *format_memory_size (u8 * s, va_list * va);
320
321 /* Parse memory page size e.g. 4K, 2M */
322 unformat_function_t unformat_log2_page_size;
323
324 /* Unparse memory page size e.g. 4K, 2M */
325 u8 *format_log2_page_size (u8 * s, va_list * va);
326
327 /* Format c identifier: e.g. a_name -> "a name". */
328 u8 *format_c_identifier (u8 * s, va_list * va);
329
330 /* Format hexdump with both hex and printable chars - compatible with text2pcap */
331 u8 *format_hexdump (u8 * s, va_list * va);
332 u8 *format_hexdump_u16 (u8 *s, va_list *va);
333 u8 *format_hexdump_u32 (u8 *s, va_list *va);
334 u8 *format_hexdump_u64 (u8 *s, va_list *va);
335
336 /* Format bitmap of array of uword numbers */
337 u8 *format_uword_bitmap (u8 *s, va_list *va);
338
339 /* Unix specific formats. */
340 #ifdef CLIB_UNIX
341 /* Setup input from Unix file. */
342 void unformat_init_clib_file (unformat_input_t * input, int file_descriptor);
343
344 /* Setup input from flesystem path. */
345 uword unformat_init_file (unformat_input_t *input, char *fmt, ...);
346
347 /* Take input from Unix environment variable; returns
348    1 if variable exists zero otherwise. */
349 uword unformat_init_unix_env (unformat_input_t * input, char *var);
350
351 /* Unformat unix group id (gid) specified as integer or string */
352 unformat_function_t unformat_unix_gid;
353 #endif /* CLIB_UNIX */
354
355 uword unformat_data_size (unformat_input_t * input, va_list * args);
356
357 /* Test code. */
358 int test_format_main (unformat_input_t * input);
359 int test_unformat_main (unformat_input_t * input);
360
361 /* This is not the right place for this, but putting it in vec.h
362 created circular dependency problems. */
363 int test_vec_main (unformat_input_t * input);
364
365 #endif /* included_format_h */
366
367 /*
368  * fd.io coding-style-patch-verification: ON
369  *
370  * Local Variables:
371  * eval: (c-set-style "gnu")
372  * End:
373  */