FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
unformat.c
Go to the documentation of this file.
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 /* Call user's function to fill input buffer. */
41 __clib_export uword
42 _unformat_fill_input (unformat_input_t * i)
43 {
44  uword l, first_mark;
45 
46  if (i->index == UNFORMAT_END_OF_INPUT)
47  return i->index;
48 
49  first_mark = l = vec_len (i->buffer);
50  if (vec_len (i->buffer_marks) > 0)
51  first_mark = i->buffer_marks[0];
52 
53  /* Re-use buffer when no marks. */
54  if (first_mark > 0)
55  vec_delete (i->buffer, first_mark, 0);
56 
57  i->index = vec_len (i->buffer);
58  for (l = 0; l < vec_len (i->buffer_marks); l++)
59  i->buffer_marks[l] -= first_mark;
60 
61  /* Call user's function to fill the buffer. */
62  if (i->fill_buffer)
63  i->index = i->fill_buffer (i);
64 
65  /* If input pointer is still beyond end of buffer even after
66  fill then we've run out of input. */
67  if (i->index >= vec_len (i->buffer))
68  i->index = UNFORMAT_END_OF_INPUT;
69 
70  return i->index;
71 }
72 
75 {
76  switch (c)
77  {
78  case ' ':
79  case '\t':
80  case '\n':
81  case '\r':
82  return 1;
83 
84  default:
85  return 0;
86  }
87 }
88 
89 /* Format function for dumping input stream. */
90 __clib_export u8 *
91 format_unformat_error (u8 * s, va_list * va)
92 {
93  unformat_input_t *i = va_arg (*va, unformat_input_t *);
94  uword l = vec_len (i->buffer);
95 
96  /* Only show so much of the input buffer (it could be really large). */
97  uword n_max = 30;
98 
99  if (i->index < l)
100  {
101  uword n = l - i->index;
102  u8 *p, *p_end;
103 
104  p = i->buffer + i->index;
105  p_end = p + (n > n_max ? n_max : n);
106 
107  /* Skip white space at end. */
108  if (n <= n_max)
109  {
110  while (p_end > p && is_white_space (p_end[-1]))
111  p_end--;
112  }
113 
114  while (p < p_end)
115  {
116  switch (*p)
117  {
118  case '\r':
119  vec_add (s, "\\r", 2);
120  break;
121  case '\n':
122  vec_add (s, "\\n", 2);
123  break;
124  case '\t':
125  vec_add (s, "\\t", 2);
126  break;
127  default:
128  vec_add1 (s, *p);
129  break;
130  }
131  p++;
132  }
133 
134  if (n > n_max)
135  vec_add (s, "...", 3);
136  }
137 
138  return s;
139 }
140 
141 /* Print everything: not just error context. */
142 __clib_export u8 *
143 format_unformat_input (u8 * s, va_list * va)
144 {
145  unformat_input_t *i = va_arg (*va, unformat_input_t *);
146  uword l, n;
147 
148  if (i->index == UNFORMAT_END_OF_INPUT)
149  s = format (s, "{END_OF_INPUT}");
150  else
151  {
152  l = vec_len (i->buffer);
153  n = l - i->index;
154  if (n > 0)
155  vec_add (s, i->buffer + i->index, n);
156  }
157 
158  return s;
159 }
160 
161 #if CLIB_DEBUG > 0
162 void
164 {
165  fformat (stderr, "%U\n", format_unformat_input, i);
166 }
167 #endif
168 
169 /* Parse delimited vector string. If string starts with { then string
170  is delimited by balanced parenthesis. Other string is delimited by
171  white space. {} were chosen since they are special to the shell. */
172 static uword
174  uword delimiter_character,
175  uword format_character, va_list * va)
176 {
177  u8 **string_return = va_arg (*va, u8 **);
178  u8 *s = 0;
179  word paren = 0;
180  word is_paren_delimited = 0;
181  word backslash = 0;
182  uword c;
183 
184  switch (delimiter_character)
185  {
186  case '%':
187  case ' ':
188  case '\t':
189  delimiter_character = 0;
190  break;
191  }
192 
193  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
194  {
195  word add_to_vector;
196 
197  /* Null return string means to skip over delimited input. */
198  add_to_vector = string_return != 0;
199 
200  if (backslash)
201  backslash = 0;
202  else
203  switch (c)
204  {
205  case '\\':
206  backslash = 1;
207  add_to_vector = 0;
208  break;
209 
210  case '{':
211  if (paren == 0 && vec_len (s) == 0)
212  {
213  is_paren_delimited = 1;
214  add_to_vector = 0;
215  }
216  paren++;
217  break;
218 
219  case '}':
220  paren--;
221  if (is_paren_delimited && paren == 0)
222  goto done;
223  break;
224 
225  case ' ':
226  case '\t':
227  case '\n':
228  case '\r':
229  if (!is_paren_delimited)
230  {
231  unformat_put_input (input);
232  goto done;
233  }
234  break;
235 
236  default:
237  if (!is_paren_delimited && c == delimiter_character)
238  {
239  unformat_put_input (input);
240  goto done;
241  }
242  }
243 
244  if (add_to_vector)
245  vec_add1 (s, c);
246  }
247 
248 done:
249  if (string_return)
250  {
251  /* Match the string { END-OF-INPUT as a single brace. */
252  if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0 && paren == 1)
253  vec_add1 (s, '{');
254 
255  /* Don't match null string. */
256  if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0)
257  return 0;
258 
259  /* Null terminate C string. */
260  if (format_character == 's')
261  vec_add1 (s, 0);
262 
263  *string_return = s;
264  }
265  else
266  vec_free (s); /* just to make sure */
267 
268  return 1;
269 }
270 
271 __clib_export uword
272 unformat_hex_string (unformat_input_t * input, va_list * va)
273 {
274  u8 **hexstring_return = va_arg (*va, u8 **);
275  u8 *s;
276  uword n, d, c;
277 
278  n = 0;
279  d = 0;
280  s = 0;
281  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
282  {
283  if (c >= '0' && c <= '9')
284  d = 16 * d + c - '0';
285  else if (c >= 'a' && c <= 'f')
286  d = 16 * d + 10 + c - 'a';
287  else if (c >= 'A' && c <= 'F')
288  d = 16 * d + 10 + c - 'A';
289  else
290  {
291  unformat_put_input (input);
292  break;
293  }
294  n++;
295 
296  if (n == 2)
297  {
298  vec_add1 (s, d);
299  n = d = 0;
300  }
301  }
302 
303  /* Hex string must have even number of digits. */
304  if (n % 2)
305  {
306  vec_free (s);
307  return 0;
308  }
309  /* Make sure something was processed. */
310  else if (s == 0)
311  {
312  return 0;
313  }
314 
315  *hexstring_return = s;
316  return 1;
317 }
318 
319 /* unformat (input "foo%U", unformat_eof) matches terminal foo only */
320 __clib_export uword
321 unformat_eof (unformat_input_t * input, va_list * va)
322 {
324 }
325 
326 /* Parse a token containing given set of characters. */
327 __clib_export uword
328 unformat_token (unformat_input_t * input, va_list * va)
329 {
330  u8 *token_chars = va_arg (*va, u8 *);
331  u8 **string_return = va_arg (*va, u8 **);
332  u8 *s, map[256];
333  uword i, c;
334 
335  if (!token_chars)
336  token_chars = (u8 *) "a-zA-Z0-9_";
337 
338  clib_memset (map, 0, sizeof (map));
339  for (s = token_chars; *s;)
340  {
341  /*
342  * Parse range.
343  * The test order is important: s[1] is valid because s[0] != '\0' but
344  * s[2] might not if s[1] == '\0'
345  * Also, if s[1] == '-' but s[2] == '\0' the test s[0] < s[2] will
346  * (correctly) fail
347  */
348  if (s[1] == '-' && s[0] < s[2])
349  {
350  for (i = s[0]; i <= s[2]; i++)
351  map[i] = 1;
352  s = s + 3;
353  }
354  else
355  {
356  map[s[0]] = 1;
357  s = s + 1;
358  }
359  }
360 
361  s = 0;
362  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
363  {
364  if (!map[c])
365  {
366  unformat_put_input (input);
367  break;
368  }
369 
370  vec_add1 (s, c);
371  }
372 
373  if (vec_len (s) == 0)
374  return 0;
375 
376  *string_return = s;
377  return 1;
378 }
379 
380 /* Unformat (parse) function which reads a %s string and converts it
381  to and unformat_input_t. */
382 __clib_export uword
383 unformat_input (unformat_input_t * i, va_list * args)
384 {
385  unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
386  u8 *s;
387 
388  if (unformat (i, "%v", &s))
389  {
390  unformat_init_vector (sub_input, s);
391  return 1;
392  }
393 
394  return 0;
395 }
396 
397 /* Parse a line ending with \n and return it. */
398 __clib_export uword
400 {
401  u8 *line = 0, **result = va_arg (*va, u8 **);
402  uword c;
403 
404  while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT)
405  {
406  vec_add1 (line, c);
407  }
408 
409  *result = line;
410  return vec_len (line);
411 }
412 
413 /* Parse a line ending with \n and return it as an unformat_input_t. */
414 __clib_export uword
416 {
417  unformat_input_t *result = va_arg (*va, unformat_input_t *);
418  u8 *line;
419  if (!unformat_user (i, unformat_line, &line))
420  return 0;
421  unformat_init_vector (result, line);
422  return 1;
423 }
424 
425 /* Values for is_signed. */
426 #define UNFORMAT_INTEGER_SIGNED 1
427 #define UNFORMAT_INTEGER_UNSIGNED 0
428 
429 static uword
431  va_list * va, uword base, uword is_signed, uword data_bytes)
432 {
433  uword c, digit;
434  uword value = 0;
435  uword n_digits = 0;
436  uword n_input = 0;
437  uword sign = 0;
438 
439  /* We only support bases <= 64. */
440  if (base < 2 || base > 64)
441  goto error;
442 
443  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
444  {
445  switch (c)
446  {
447  case '-':
448  if (n_input == 0)
449  {
450  if (is_signed)
451  {
452  sign = 1;
453  goto next_digit;
454  }
455  else
456  /* Leading sign for unsigned number. */
457  goto error;
458  }
459  /* Sign after input (e.g. 100-200). */
460  goto put_input_done;
461 
462  case '+':
463  if (n_input > 0)
464  goto put_input_done;
465  sign = 0;
466  goto next_digit;
467 
468  case '0' ... '9':
469  digit = c - '0';
470  break;
471 
472  case 'a' ... 'z':
473  digit = 10 + (c - 'a');
474  break;
475 
476  case 'A' ... 'Z':
477  digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A');
478  break;
479 
480  case '/':
481  digit = 62;
482  break;
483 
484  case '?':
485  digit = 63;
486  break;
487 
488  default:
489  goto put_input_done;
490  }
491 
492  if (digit >= base)
493  {
494  put_input_done:
495  unformat_put_input (input);
496  goto done;
497  }
498 
499  {
500  uword new_value = base * value + digit;
501 
502  /* Check for overflow. */
503  if (new_value < value)
504  goto error;
505  value = new_value;
506  }
507  n_digits += 1;
508 
509  next_digit:
510  n_input++;
511  }
512 
513 done:
514  if (sign)
515  value = -value;
516 
517  if (n_digits > 0)
518  {
519  void *v = va_arg (*va, void *);
520 
521  if (data_bytes == ~0)
522  data_bytes = sizeof (int);
523 
524  switch (data_bytes)
525  {
526  case 1:
527  *(u8 *) v = value;
528  break;
529  case 2:
530  *(u16 *) v = value;
531  break;
532  case 4:
533  *(u32 *) v = value;
534  break;
535  case 8:
536  *(u64 *) v = value;
537  break;
538  default:
539  goto error;
540  }
541 
542  return 1;
543  }
544 
545 error:
546  return 0;
547 }
548 
549 /* Return x 10^n */
550 static f64
552 {
553  if (n >= 0)
554  {
555  static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
556  while (n >= 8)
557  {
558  x *= 1e+8;
559  n -= 8;
560  }
561  return x * t[n];
562  }
563  else
564  {
565  static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
566  while (n <= -8)
567  {
568  x *= 1e-8;
569  n += 8;
570  }
571  return x * t[-n];
572  }
573 
574 }
575 
576 static uword
577 unformat_float (unformat_input_t * input, va_list * va)
578 {
579  uword c;
580  u64 values[3];
581  uword n_digits[3], value_index = 0;
582  uword signs[2], sign_index = 0;
583  uword n_input = 0;
584 
585  clib_memset (values, 0, sizeof (values));
586  clib_memset (n_digits, 0, sizeof (n_digits));
587  clib_memset (signs, 0, sizeof (signs));
588 
589  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
590  {
591  switch (c)
592  {
593  case '-':
594  if (value_index == 2 && n_digits[2] == 0)
595  /* sign of exponent: it's ok. */ ;
596 
597  else if (value_index < 2 && n_digits[0] > 0)
598  {
599  /* 123- */
600  unformat_put_input (input);
601  goto done;
602  }
603 
604  else if (n_input > 0)
605  goto error;
606 
607  signs[sign_index++] = 1;
608  goto next_digit;
609 
610  case '+':
611  if (value_index == 2 && n_digits[2] == 0)
612  /* sign of exponent: it's ok. */ ;
613 
614  else if (value_index < 2 && n_digits[0] > 0)
615  {
616  /* 123+ */
617  unformat_put_input (input);
618  goto done;
619  }
620 
621  else if (n_input > 0)
622  goto error;
623  signs[sign_index++] = 0;
624  goto next_digit;
625 
626  case 'e':
627  case 'E':
628  if (n_input == 0)
629  goto error;
630  value_index = 2;
631  sign_index = 1;
632  break;
633 
634  case '.':
635  if (value_index > 0)
636  goto error;
637  value_index = 1;
638  break;
639 
640  case '0' ... '9':
641  {
642  u64 tmp;
643 
644  tmp = values[value_index] * 10 + c - '0';
645 
646  /* Check for overflow. */
647  if (tmp < values[value_index])
648  goto error;
649  values[value_index] = tmp;
650  n_digits[value_index] += 1;
651  }
652  break;
653 
654  default:
655  unformat_put_input (input);
656  goto done;
657  }
658 
659  next_digit:
660  n_input++;
661  }
662 
663 done:
664  {
665  f64 f_values[2], *value_return;
666  word expon;
667 
668  /* Must have either whole or fraction digits. */
669  if (n_digits[0] + n_digits[1] <= 0)
670  goto error;
671 
672  f_values[0] = values[0];
673  if (signs[0])
674  f_values[0] = -f_values[0];
675 
676  f_values[1] = values[1];
677  f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]);
678 
679  f_values[0] += f_values[1];
680 
681  expon = values[2];
682  if (signs[1])
683  expon = -expon;
684 
685  f_values[0] = times_power_of_ten (f_values[0], expon);
686 
687  value_return = va_arg (*va, f64 *);
688  *value_return = f_values[0];
689  return 1;
690  }
691 
692 error:
693  return 0;
694 }
695 
696 static const char *
698 {
699  uword cf, ci;
700 
701  ASSERT (*f != 0);
702 
703  while (1)
704  {
705  cf = *f;
706  if (cf == 0 || cf == '%' || cf == ' ')
707  break;
708  f++;
709 
710  ci = unformat_get_input (input);
711 
712  if (cf != ci)
713  return 0;
714  }
715  return f;
716 }
717 
718 static const char *
719 do_percent (unformat_input_t * input, va_list * va, const char *f)
720 {
721  uword cf, n, data_bytes = ~0;
722 
723  cf = *f++;
724 
725  switch (cf)
726  {
727  default:
728  break;
729 
730  case 'w':
731  /* Word types. */
732  cf = *f++;
733  data_bytes = sizeof (uword);
734  break;
735 
736  case 'l':
737  cf = *f++;
738  if (cf == 'l')
739  {
740  cf = *f++;
741  data_bytes = sizeof (long long);
742  }
743  else
744  {
745  data_bytes = sizeof (long);
746  }
747  break;
748 
749  case 'L':
750  cf = *f++;
751  data_bytes = sizeof (long long);
752  break;
753  }
754 
755  n = 0;
756  switch (cf)
757  {
758  case 'D':
759  data_bytes = va_arg (*va, int);
760  case 'd':
761  n = unformat_integer (input, va, 10,
762  UNFORMAT_INTEGER_SIGNED, data_bytes);
763  break;
764 
765  case 'u':
766  n = unformat_integer (input, va, 10,
767  UNFORMAT_INTEGER_UNSIGNED, data_bytes);
768  break;
769 
770  case 'b':
771  n = unformat_integer (input, va, 2,
772  UNFORMAT_INTEGER_UNSIGNED, data_bytes);
773  break;
774 
775  case 'o':
776  n = unformat_integer (input, va, 8,
777  UNFORMAT_INTEGER_UNSIGNED, data_bytes);
778  break;
779 
780  case 'X':
781  data_bytes = va_arg (*va, int);
782  case 'x':
783  n = unformat_integer (input, va, 16,
784  UNFORMAT_INTEGER_UNSIGNED, data_bytes);
785  break;
786 
787  case 'f':
788  n = unformat_float (input, va);
789  break;
790 
791  case 's':
792  case 'v':
793  n = unformat_string (input, f[0], cf, va);
794  break;
795 
796  case 'U':
797  {
798  unformat_function_t *f = va_arg (*va, unformat_function_t *);
799  n = f (input, va);
800  }
801  break;
802 
803  case '=':
804  case '|':
805  {
806  int *var = va_arg (*va, int *);
807  uword val = va_arg (*va, int);
808 
809  if (cf == '|')
810  val |= *var;
811  *var = val;
812  n = 1;
813  }
814  break;
815  }
816 
817  return n ? f : 0;
818 }
819 
820 __clib_export uword
822 {
823  uword n = 0;
824  uword c;
825 
826  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
827  {
828  if (!is_white_space (c))
829  {
830  unformat_put_input (input);
831  break;
832  }
833  n++;
834  }
835  return n;
836 }
837 
838 __clib_export uword
839 va_unformat (unformat_input_t * input, const char *fmt, va_list * va)
840 {
841  const char *f;
842  uword input_matches_format;
843  uword default_skip_input_white_space;
844  uword n_input_white_space_skipped;
845  uword last_non_white_space_match_percent;
846  uword last_non_white_space_match_format;
847 
848  vec_add1_aligned (input->buffer_marks, input->index,
849  sizeof (input->buffer_marks[0]));
850 
851  f = fmt;
852  default_skip_input_white_space = 1;
853  input_matches_format = 0;
854  last_non_white_space_match_percent = 0;
855  last_non_white_space_match_format = 0;
856 
857  while (1)
858  {
859  char cf;
860  uword is_percent, skip_input_white_space;
861 
862  cf = *f;
863  is_percent = 0;
864 
865  /* Always skip input white space at start of format string.
866  Otherwise use default skip value which can be changed by %_
867  (see below). */
868  skip_input_white_space = f == fmt || default_skip_input_white_space;
869 
870  /* Spaces in format request skipping input white space. */
871  if (is_white_space (cf))
872  {
873  skip_input_white_space = 1;
874 
875  /* Multiple format spaces are equivalent to a single white
876  space. */
877  while (is_white_space (*++f))
878  ;
879  }
880  else if (cf == '%')
881  {
882  /* %_ toggles whether or not to skip input white space. */
883  switch (*++f)
884  {
885  case '_':
886  default_skip_input_white_space =
887  !default_skip_input_white_space;
888  f++;
889  /* For transition from skip to no-skip in middle of format
890  string, skip input white space. For example, the following matches:
891  fmt = "%_%d.%d%_->%_%d.%d%_"
892  input "1.2 -> 3.4"
893  Without this the space after -> does not get skipped. */
894  if (!default_skip_input_white_space
895  && !(f == fmt + 2 || *f == 0))
897  continue;
898 
899  /* %% means match % */
900  case '%':
901  break;
902 
903  /* % at end of format string. */
904  case 0:
905  goto parse_fail;
906 
907  default:
908  is_percent = 1;
909  break;
910  }
911  }
912 
913  n_input_white_space_skipped = 0;
914  if (skip_input_white_space)
915  n_input_white_space_skipped = unformat_skip_white_space (input);
916 
917  /* End of format string. */
918  if (cf == 0)
919  {
920  /* Force parse error when format string ends and input is
921  not white or at end. As an example, this is to prevent
922  format "foo" from matching input "food".
923  The last_non_white_space_match_percent is to make
924  "foo %d" match input "foo 10,bletch" with %d matching 10. */
925  if (skip_input_white_space
926  && !last_non_white_space_match_percent
927  && !last_non_white_space_match_format
928  && n_input_white_space_skipped == 0
929  && input->index != UNFORMAT_END_OF_INPUT)
930  goto parse_fail;
931  break;
932  }
933 
934  last_non_white_space_match_percent = is_percent;
935  last_non_white_space_match_format = 0;
936 
937  /* Explicit spaces in format must match input white space. */
938  if (cf == ' ' && !default_skip_input_white_space)
939  {
940  if (n_input_white_space_skipped == 0)
941  goto parse_fail;
942  }
943 
944  else if (is_percent)
945  {
946  if (!(f = do_percent (input, va, f)))
947  goto parse_fail;
948  }
949 
950  else
951  {
952  const char *g = match_input_with_format (input, f);
953  if (!g)
954  goto parse_fail;
955  last_non_white_space_match_format = g > f;
956  f = g;
957  }
958  }
959 
960  input_matches_format = 1;
961 parse_fail:
962 
963  /* Rewind buffer marks. */
964  {
965  uword l = vec_len (input->buffer_marks);
966 
967  /* If we did not match back up buffer to last mark. */
968  if (!input_matches_format)
969  input->index = input->buffer_marks[l - 1];
970 
971  _vec_len (input->buffer_marks) = l - 1;
972  }
973 
974  return input_matches_format;
975 }
976 
977 __clib_export uword
978 unformat (unformat_input_t * input, const char *fmt, ...)
979 {
980  va_list va;
981  uword result;
982  va_start (va, fmt);
983  result = va_unformat (input, fmt, &va);
984  va_end (va);
985  return result;
986 }
987 
988 __clib_export uword
990 {
991  va_list va;
992  uword result, l;
993 
994  /* Save place in input buffer in case parse fails. */
995  l = vec_len (input->buffer_marks);
996  vec_add1_aligned (input->buffer_marks, input->index,
997  sizeof (input->buffer_marks[0]));
998 
999  va_start (va, func);
1000  result = func (input, &va);
1001  va_end (va);
1002 
1003  if (!result && input->index != UNFORMAT_END_OF_INPUT)
1004  input->index = input->buffer_marks[l];
1005 
1006  _vec_len (input->buffer_marks) = l;
1007 
1008  return result;
1009 }
1010 
1011 /* Setup for unformat of Unix style command line. */
1012 __clib_export void
1014 {
1015  uword i;
1016 
1017  unformat_init (input, 0, 0);
1018 
1019  /* Concatenate argument strings with space in between. */
1020  for (i = 1; argv[i]; i++)
1021  {
1022  vec_add (input->buffer, argv[i], strlen (argv[i]));
1023  if (argv[i + 1])
1024  vec_add1 (input->buffer, ' ');
1025  }
1026 }
1027 
1028 __clib_export void
1029 unformat_init_string (unformat_input_t * input, char *string, int string_len)
1030 {
1031  unformat_init (input, 0, 0);
1032  if (string_len > 0)
1033  vec_add (input->buffer, string, string_len);
1034 }
1035 
1036 __clib_export void
1037 unformat_init_vector (unformat_input_t * input, u8 * vector_string)
1038 {
1039  unformat_init (input, 0, 0);
1040  input->buffer = vector_string;
1041 }
1042 
1043 #ifdef CLIB_UNIX
1044 
1045 static uword
1047 {
1048  int fd = pointer_to_uword (input->fill_buffer_arg);
1049  uword l, n;
1050 
1051  l = vec_len (input->buffer);
1052  vec_resize (input->buffer, 4096);
1053  n = read (fd, input->buffer + l, 4096);
1054  if (n > 0)
1055  _vec_len (input->buffer) = l + n;
1056 
1057  if (n <= 0)
1058  return UNFORMAT_END_OF_INPUT;
1059  else
1060  return input->index;
1061 }
1062 
1063 __clib_export void
1064 unformat_init_clib_file (unformat_input_t * input, int file_descriptor)
1065 {
1067  uword_to_pointer (file_descriptor, void *));
1068 }
1069 
1070 /* Take input from Unix environment variable. */
1071 uword
1073 {
1074  char *val = getenv (var);
1075  if (val)
1076  unformat_init_string (input, val, strlen (val));
1077  return val != 0;
1078 }
1079 
1080 __clib_export uword
1081 unformat_data_size (unformat_input_t * input, va_list * args)
1082 {
1083  u64 _a;
1084  u64 *a = va_arg (*args, u64 *);
1085  if (unformat (input, "%lluGb", &_a))
1086  *a = _a << 30;
1087  else if (unformat (input, "%lluG", &_a))
1088  *a = _a << 30;
1089  else if (unformat (input, "%lluMb", &_a))
1090  *a = _a << 20;
1091  else if (unformat (input, "%lluM", &_a))
1092  *a = _a << 20;
1093  else if (unformat (input, "%lluKb", &_a))
1094  *a = _a << 10;
1095  else if (unformat (input, "%lluK", &_a))
1096  *a = _a << 10;
1097  else if (unformat (input, "%llu", a))
1098  ;
1099  else
1100  return 0;
1101  return 1;
1102 }
1103 
1104 #endif /* CLIB_UNIX */
1105 
1106 
1107 /*
1108  * fd.io coding-style-patch-verification: ON
1109  *
1110  * Local Variables:
1111  * eval: (c-set-style "gnu")
1112  * End:
1113  */
tmp
u32 * tmp
Definition: interface_output.c:1096
unformat_float
static uword unformat_float(unformat_input_t *input, va_list *va)
Definition: unformat.c:577
vec_add
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:688
unformat_input
__clib_export uword unformat_input(unformat_input_t *i, va_list *args)
Definition: unformat.c:383
unformat_skip_white_space
__clib_export uword unformat_skip_white_space(unformat_input_t *input)
Definition: unformat.c:821
f
vlib_frame_t * f
Definition: interface_output.c:1098
pointer_to_uword
static uword pointer_to_uword(const void *p)
Definition: types.h:131
unformat_eof
__clib_export uword unformat_eof(unformat_input_t *input, va_list *va)
Definition: unformat.c:321
u16
unsigned short u16
Definition: types.h:57
unformat_token
__clib_export uword unformat_token(unformat_input_t *input, va_list *va)
Definition: unformat.c:328
vec_delete
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:875
match_input_with_format
static const char * match_input_with_format(unformat_input_t *input, const char *f)
Definition: unformat.c:697
unformat_hex_string
__clib_export uword unformat_hex_string(unformat_input_t *input, va_list *va)
Definition: unformat.c:272
unformat_input_t
struct _unformat_input_t unformat_input_t
error
Definition: cJSON.c:88
unformat_init_vector
__clib_export void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1037
va_unformat
__clib_export uword va_unformat(unformat_input_t *input, const char *fmt, va_list *va)
Definition: unformat.c:839
unformat_put_input
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:197
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
map
counters map
Definition: map.api:356
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
c
svmdb_client_t * c
Definition: vpp_get_metrics.c:48
uword
u64 uword
Definition: types.h:112
if
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
f64
double f64
Definition: types.h:142
unformat_line_input
__clib_export uword unformat_line_input(unformat_input_t *i, va_list *va)
Definition: unformat.c:415
format.h
clib_file_fill_buffer
static uword clib_file_fill_buffer(unformat_input_t *input)
Definition: unformat.c:1046
unformat_get_input
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:184
fmt
int cJSON_bool fmt
Definition: cJSON.h:160
unformat_string
static uword unformat_string(unformat_input_t *input, uword delimiter_character, uword format_character, va_list *va)
Definition: unformat.c:173
times_power_of_ten
static f64 times_power_of_ten(f64 x, int n)
Definition: unformat.c:551
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
u64
unsigned long u64
Definition: types.h:89
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vec_add1_aligned
#define vec_add1_aligned(V, E, A)
Add 1 element to end of vector (alignment specified).
Definition: vec.h:615
u32
unsigned int u32
Definition: types.h:88
unformat_function_t
uword() unformat_function_t(unformat_input_t *input, va_list *args)
Definition: format.h:225
vec_resize
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V,...
Definition: vec.h:296
value
u8 value
Definition: qos.api:54
fformat
__clib_export word fformat(FILE *f, char *fmt,...)
Definition: format.c:466
unformat_user
__clib_export uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
UNFORMAT_INTEGER_UNSIGNED
#define UNFORMAT_INTEGER_UNSIGNED
Definition: unformat.c:427
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
unformat_init_unix_env
uword unformat_init_unix_env(unformat_input_t *input, char *var)
Definition: unformat.c:1072
u8
unsigned char u8
Definition: types.h:56
a
a
Definition: bitmap.h:525
unformat_line
__clib_export uword unformat_line(unformat_input_t *i, va_list *va)
Definition: unformat.c:399
format_unformat_input
__clib_export u8 * format_unformat_input(u8 *s, va_list *va)
Definition: unformat.c:143
uword_to_pointer
#define uword_to_pointer(u, type)
Definition: types.h:136
i
int i
Definition: flowhash_template.h:376
unformat_init_clib_file
__clib_export void unformat_init_clib_file(unformat_input_t *input, int file_descriptor)
Definition: unformat.c:1064
word
i64 word
Definition: types.h:111
UNFORMAT_INTEGER_SIGNED
#define UNFORMAT_INTEGER_SIGNED
Definition: unformat.c:426
unformat
__clib_export uword unformat(unformat_input_t *input, const char *fmt,...)
Definition: unformat.c:978
di
void di(unformat_input_t *i)
Definition: unformat.c:163
unformat_integer
static uword unformat_integer(unformat_input_t *input, va_list *va, uword base, uword is_signed, uword data_bytes)
Definition: unformat.c:430
do_percent
static const char * do_percent(unformat_input_t *input, va_list *va, const char *f)
Definition: unformat.c:719
unformat_init
static void unformat_init(unformat_input_t *i, uword(*fill_buffer)(unformat_input_t *), void *fill_buffer_arg)
Definition: format.h:145
unformat_init_command_line
__clib_export void unformat_init_command_line(unformat_input_t *input, char *argv[])
Definition: unformat.c:1013
is_white_space
static uword is_white_space(uword c)
Definition: unformat.c:74
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
unformat_init_string
__clib_export void unformat_init_string(unformat_input_t *input, char *string, int string_len)
Definition: unformat.c:1029
unformat_data_size
__clib_export uword unformat_data_size(unformat_input_t *input, va_list *args)
Definition: unformat.c:1081
format_unformat_error
__clib_export u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91