FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
format.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  * format.c -- see notice below
17  *
18  * October 2003, Eliot Dresselhaus
19  *
20  * Modifications to this file Copyright (c) 2003 by cisco Systems, Inc.
21  * All rights reserved.
22  *------------------------------------------------------------------
23  */
24 
25 /*
26  Copyright (c) 2001, 2002, 2003, 2006 Eliot Dresselhaus
27 
28  Permission is hereby granted, free of charge, to any person obtaining
29  a copy of this software and associated documentation files (the
30  "Software"), to deal in the Software without restriction, including
31  without limitation the rights to use, copy, modify, merge, publish,
32  distribute, sublicense, and/or sell copies of the Software, and to
33  permit persons to whom the Software is furnished to do so, subject to
34  the following conditions:
35 
36  The above copyright notice and this permission notice shall be
37  included in all copies or substantial portions of the Software.
38 
39  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
40  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
42  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
43  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
44  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
45  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46 */
47 
48 #include <stdarg.h> /* va_start, etc */
49 
50 #ifdef CLIB_UNIX
51 #include <unistd.h>
52 #include <stdio.h>
53 #endif
54 
55 #ifdef CLIB_STANDALONE
56 #include <vppinfra/standalone_stdio.h>
57 #endif
58 
59 #include <vppinfra/mem.h>
60 #include <vppinfra/format.h>
61 #include <vppinfra/vec.h>
62 #include <vppinfra/error.h>
63 #include <vppinfra/string.h>
64 #include <vppinfra/os.h> /* os_puts */
65 #include <vppinfra/math.h>
66 
67 typedef struct
68 {
69  /* Output number in this base. */
71 
72  /* Number of show of 64 bit number. */
74 
75  /* Signed or unsigned. */
77 
78  /* Output digits uppercase (not lowercase) %X versus %x. */
81 
82 static u8 *format_integer (u8 * s, u64 number,
84 static u8 *format_float (u8 * s, f64 x, uword n_digits_to_print,
85  uword output_style);
86 
87 typedef struct
88 {
89  /* String justification: + => right, - => left, = => center. */
91 
92  /* Width of string (before and after decimal point for numbers).
93  0 => natural width. */
94  uword width[2];
95 
96  /* Long => 'l', long long 'L', int 0. */
98 
99  /* Pad character. Defaults to space. */
101 } format_info_t;
102 
103 static u8 *
104 justify (u8 * s, format_info_t * fi, uword s_len_orig)
105 {
106  uword i0, l0, l1;
107 
108  i0 = s_len_orig;
109  l0 = i0 + fi->width[0];
110  l1 = vec_len (s);
111 
112  /* If width is zero user returned width. */
113  if (l0 == i0)
114  l0 = l1;
115 
116  if (l1 > l0)
117  _vec_len (s) = l0;
118  else if (l0 > l1)
119  {
120  uword n = l0 - l1;
121  uword n_left = 0, n_right = 0;
122 
123  switch (fi->justify)
124  {
125  case '-':
126  n_right = n;
127  break;
128 
129  case '+':
130  n_left = n;
131  break;
132 
133  case '=':
134  n_right = n_left = n / 2;
135  if (n % 2)
136  n_left++;
137  break;
138  }
139  if (n_left > 0)
140  {
141  vec_insert (s, n_left, i0);
142  clib_memset (s + i0, fi->pad_char, n_left);
143  l1 = vec_len (s);
144  }
145  if (n_right > 0)
146  {
147  vec_resize (s, n_right);
148  clib_memset (s + l1, fi->pad_char, n_right);
149  }
150  }
151  return s;
152 }
153 
154 static const u8 *
155 do_percent (u8 ** _s, const u8 * fmt, va_list * va)
156 {
157  u8 *s = *_s;
158  uword c;
159 
160  const u8 *f = fmt;
161 
162  format_info_t fi = {
163  .justify = '+',
164  .width = {0},
165  .pad_char = ' ',
166  .how_long = 0,
167  };
168 
169  uword i;
170 
171  ASSERT (f[0] == '%');
172 
173  switch (c = *++f)
174  {
175  case '%':
176  /* %% => % */
177  vec_add1 (s, c);
178  f++;
179  goto done;
180 
181  case '-':
182  case '+':
183  case '=':
184  fi.justify = c;
185  c = *++f;
186  break;
187  }
188 
189  /* Parse width0 . width1. */
190  {
191  uword is_first_digit = 1;
192 
193  fi.width[0] = fi.width[1] = 0;
194  for (i = 0; i < 2; i++)
195  {
196  if (c == '0' && i == 0 && is_first_digit)
197  fi.pad_char = '0';
198  is_first_digit = 0;
199  if (c == '*')
200  {
201  fi.width[i] = va_arg (*va, int);
202  c = *++f;
203  }
204  else
205  {
206  while (c >= '0' && c <= '9')
207  {
208  fi.width[i] = 10 * fi.width[i] + (c - '0');
209  c = *++f;
210  }
211  }
212  if (c != '.')
213  break;
214  c = *++f;
215  }
216  }
217 
218  /* Parse %l* and %L* */
219  switch (c)
220  {
221  case 'w':
222  /* word format. */
223  fi.how_long = 'w';
224  c = *++f;
225  break;
226 
227  case 'L':
228  case 'l':
229  fi.how_long = c;
230  c = *++f;
231  if (c == 'l' && *f == 'l')
232  {
233  fi.how_long = 'L';
234  c = *++f;
235  }
236  break;
237  }
238 
239  /* Finally we are ready for format letter. */
240  if (c != 0)
241  {
242  uword s_initial_len = vec_len (s);
244  .is_signed = 0,
245  .base = 10,
246  .n_bits = BITS (uword),
247  .uppercase_digits = 0,
248  };
249 
250  f++;
251 
252  switch (c)
253  {
254  default:
255  {
256  /* Try to give a helpful error message. */
257  vec_free (s);
258  s = format (s, "**** CLIB unknown format `%%%c' ****", c);
259  goto done;
260  }
261 
262  case 'c':
263  vec_add1 (s, va_arg (*va, int));
264  break;
265 
266  case 'p':
267  vec_add1 (s, '0');
268  vec_add1 (s, 'x');
269 
270  o.is_signed = 0;
271  o.n_bits = BITS (uword *);
272  o.base = 16;
273  o.uppercase_digits = 0;
274 
275  s = format_integer (s, pointer_to_uword (va_arg (*va, void *)), &o);
276  break;
277 
278  case 'x':
279  case 'X':
280  case 'u':
281  case 'o':
282  case 'd':
283  {
284  u64 number;
285 
286  o.base = 10;
287  if (c == 'x' || c == 'X')
288  o.base = 16;
289  o.is_signed = c == 'd';
290  o.uppercase_digits = c == 'X';
291 
292  switch (fi.how_long)
293  {
294  case 'L':
295  number = va_arg (*va, unsigned long long);
296  o.n_bits = BITS (unsigned long long);
297  break;
298 
299  case 'l':
300  number = va_arg (*va, long);
301  o.n_bits = BITS (long);
302  break;
303 
304  case 'w':
305  number = va_arg (*va, word);
306  o.n_bits = BITS (uword);
307  break;
308 
309  default:
310  number = va_arg (*va, int);
311  o.n_bits = BITS (int);
312  break;
313  }
314 
315  if (c == 'o')
316  o.base = 8;
317 
318  s = format_integer (s, number, &o);
319  }
320  break;
321 
322  case 's':
323  case 'S':
324  {
325  char *cstring = va_arg (*va, char *);
326  uword len;
327 
328  if (!cstring)
329  {
330  cstring = "(nil)";
331  len = 5;
332  }
333  else if (fi.width[1] != 0)
334  len = clib_min (strlen (cstring), fi.width[1]);
335  else
336  len = strlen (cstring);
337 
338  /* %S => format string as C identifier (replace _ with space). */
339  if (c == 'S')
340  {
341  for (i = 0; i < len; i++)
342  vec_add1 (s, cstring[i] == '_' ? ' ' : cstring[i]);
343  }
344  else
345  vec_add (s, cstring, len);
346  }
347  break;
348 
349  case 'v':
350  {
351  u8 *v = va_arg (*va, u8 *);
352  uword len;
353 
354  if (fi.width[1] != 0)
355  len = clib_min (vec_len (v), fi.width[1]);
356  else
357  len = vec_len (v);
358 
359  vec_add (s, v, len);
360  }
361  break;
362 
363  case 'f':
364  case 'g':
365  case 'e':
366  /* Floating point. */
367  ASSERT (fi.how_long == 0 || fi.how_long == 'l');
368  s = format_float (s, va_arg (*va, double), fi.width[1], c);
369  break;
370 
371  case 'U':
372  /* User defined function. */
373  {
374  typedef u8 *(user_func_t) (u8 * s, va_list * args);
375  user_func_t *u = va_arg (*va, user_func_t *);
376 
377  s = (*u) (s, va);
378  }
379  break;
380  }
381 
382  s = justify (s, &fi, s_initial_len);
383  }
384 
385 done:
386  *_s = s;
387  return f;
388 }
389 
390 __clib_export u8 *
391 va_format (u8 * s, const char *fmt, va_list * va)
392 {
393  const u8 *f = (u8 *) fmt, *g;
394  u8 c;
395 
396  g = f;
397  while (1)
398  {
399  c = *f;
400 
401  if (!c)
402  break;
403 
404  if (c == '%')
405  {
406  if (f > g)
407  vec_add (s, g, f - g);
408  f = g = do_percent (&s, f, va);
409  }
410  else
411  {
412  f++;
413  }
414  }
415 
416  if (f > g)
417  vec_add (s, g, f - g);
418 
419 #ifdef __COVERITY__
420  if (s == 0)
421  return (u8 *) "liar liar pants on fire s can't be zero!";
422 #endif
423 
424  return s;
425 }
426 
427 __clib_export u8 *
428 format (u8 * s, const char *fmt, ...)
429 {
430  va_list va;
431  va_start (va, fmt);
432  s = va_format (s, fmt, &va);
433  va_end (va);
434 #ifdef __COVERITY__
435  if (s == 0)
436  return (u8 *) "liar liar pants on fire s can't be zero!";
437 #endif
438  return s;
439 }
440 
441 __clib_export word
442 va_fformat (FILE * f, char *fmt, va_list * va)
443 {
444  word ret;
445  u8 *s;
446 
447  s = va_format (0, fmt, va);
448 
449 #ifdef CLIB_UNIX
450  if (f)
451  {
452  ret = fwrite (s, vec_len (s), 1, f);
453  }
454  else
455 #endif /* CLIB_UNIX */
456  {
457  ret = 0;
458  os_puts (s, vec_len (s), /* is_error */ 0);
459  }
460 
461  vec_free (s);
462  return ret;
463 }
464 
465 __clib_export word
466 fformat (FILE * f, char *fmt, ...)
467 {
468  va_list va;
469  word ret;
470 
471  va_start (va, fmt);
472  ret = va_fformat (f, fmt, &va);
473  va_end (va);
474 
475  return (ret);
476 }
477 
478 #ifdef CLIB_UNIX
479 __clib_export void
480 fformat_append_cr (FILE * ofp, const char *fmt, ...)
481 {
482  va_list va;
483 
484  va_start (va, fmt);
485  (void) va_fformat (ofp, (char *) fmt, &va);
486  va_end (va);
487  fformat (ofp, "\n");
488 }
489 
490 __clib_export word
491 fdformat (int fd, char *fmt, ...)
492 {
493  word ret;
494  u8 *s;
495  va_list va;
496 
497  va_start (va, fmt);
498  s = va_format (0, fmt, &va);
499  va_end (va);
500 
501  ret = write (fd, s, vec_len (s));
502  vec_free (s);
503  return ret;
504 }
505 #endif
506 
507 /* Format integral type. */
508 static u8 *
510 {
511  u64 q;
512  u32 r;
513  u8 digit_buffer[128];
514  u8 *d = digit_buffer + sizeof (digit_buffer);
515  word c, base;
516 
517  if (options->is_signed && (i64) number < 0)
518  {
519  number = -number;
520  vec_add1 (s, '-');
521  }
522 
523  if (options->n_bits < BITS (number))
524  number &= ((u64) 1 << options->n_bits) - 1;
525 
526  base = options->base;
527 
528  while (1)
529  {
530  q = number / base;
531  r = number % base;
532 
533  if (r < 10 + 26 + 26)
534  {
535  if (r < 10)
536  c = '0' + r;
537  else if (r < 10 + 26)
538  c = 'a' + (r - 10);
539  else
540  c = 'A' + (r - 10 - 26);
541 
542  if (options->uppercase_digits
543  && base <= 10 + 26 && c >= 'a' && c <= 'z')
544  c += 'A' - 'a';
545 
546  *--d = c;
547  }
548  else /* will never happen, warning be gone */
549  {
550  *--d = '?';
551  }
552 
553  if (q == 0)
554  break;
555 
556  number = q;
557  }
558 
559  vec_add (s, d, digit_buffer + sizeof (digit_buffer) - d);
560  return s;
561 }
562 
563 /* Floating point formatting. */
564 /* Deconstruct IEEE 64 bit number into sign exponent and fraction. */
565 #define f64_down(f,sign,expon,fraction) \
566 do { \
567  union { u64 u; f64 f; } _f64_down_tmp; \
568  _f64_down_tmp.f = (f); \
569  (sign) = (_f64_down_tmp.u >> 63); \
570  (expon) = ((_f64_down_tmp.u >> 52) & 0x7ff) - 1023; \
571  (fraction) = ((_f64_down_tmp.u << 12) >> 12) | ((u64) 1 << 52); \
572 } while (0)
573 
574 /* Construct IEEE 64 bit number. */
575 static f64
576 f64_up (uword sign, word expon, u64 fraction)
577 {
578  union
579  {
580  u64 u;
581  f64 f;
582  } tmp;
583 
584  tmp.u = (u64) ((sign) != 0) << 63;
585 
586  expon += 1023;
587  if (expon > 1023)
588  expon = 1023;
589  if (expon < 0)
590  expon = 0;
591  tmp.u |= (u64) expon << 52;
592 
593  tmp.u |= fraction & (((u64) 1 << 52) - 1);
594 
595  return tmp.f;
596 }
597 
598 /* Returns approximate precision of number given its exponent. */
599 static f64
600 f64_precision (int base2_expon)
601 {
602  static int n_bits = 0;
603 
604  if (!n_bits)
605  {
606  /* Compute number of significant bits in floating point representation. */
607  f64 one = 0;
608  f64 small = 1;
609 
610  while (one != 1)
611  {
612  small *= .5;
613  n_bits++;
614  one = 1 + small;
615  }
616  }
617 
618  return f64_up (0, base2_expon - n_bits, 0);
619 }
620 
621 /* Return x 10^n */
622 static f64
624 {
625  if (n >= 0)
626  {
627  static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
628  while (n >= 8)
629  {
630  x *= 1e+8;
631  n -= 8;
632  }
633  return x * t[n];
634  }
635  else
636  {
637  static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
638  while (n <= -8)
639  {
640  x *= 1e-8;
641  n += 8;
642  }
643  return x * t[-n];
644  }
645 
646 }
647 
648 /* Write x = y * 10^expon with 1 < y < 10. */
649 static f64
650 normalize (f64 x, word * expon_return, f64 * prec_return)
651 {
652  word expon2, expon10;
653  CLIB_UNUSED (u64 fraction);
654  CLIB_UNUSED (word sign);
655  f64 prec;
656 
657  f64_down (x, sign, expon2, fraction);
658 
659  expon10 =
660  .5 +
661  expon2 * .301029995663981195213738894724493 /* Log (2) / Log (10) */ ;
662 
663  prec = f64_precision (expon2);
664  x = times_power_of_ten (x, -expon10);
665  prec = times_power_of_ten (prec, -expon10);
666 
667  while (x < 1)
668  {
669  x *= 10;
670  prec *= 10;
671  expon10--;
672  }
673 
674  while (x > 10)
675  {
676  x *= .1;
677  prec *= .1;
678  expon10++;
679  }
680 
681  if (x + prec >= 10)
682  {
683  x = 1;
684  expon10++;
685  }
686 
687  *expon_return = expon10;
688  *prec_return = prec;
689 
690  return x;
691 }
692 
693 static u8 *
694 add_some_zeros (u8 * s, uword n_zeros)
695 {
696  while (n_zeros > 0)
697  {
698  vec_add1 (s, '0');
699  n_zeros--;
700  }
701  return s;
702 }
703 
704 /* Format a floating point number with the given number of fractional
705  digits (e.g. 1.2345 with 2 fraction digits yields "1.23") and output style. */
706 static u8 *
707 format_float (u8 * s, f64 x, uword n_fraction_digits, uword output_style)
708 {
709  f64 prec;
710  word sign, expon, n_fraction_done, added_decimal_point;
711  /* Position of decimal point relative to where we are. */
712  word decimal_point;
713 
714  /* Default number of digits to print when its not specified. */
715  if (n_fraction_digits == ~0)
716  n_fraction_digits = 7;
717  n_fraction_done = 0;
718  decimal_point = 0;
719  added_decimal_point = 0;
720  sign = expon = 0;
721 
722  /* Special case: zero. */
723  if (x == 0)
724  {
725  do_zero:
726  vec_add1 (s, '0');
727  goto done;
728  }
729 
730  if (x < 0)
731  {
732  x = -x;
733  sign = 1;
734  }
735 
736  /* Check for not-a-number. */
737  if (isnan (x))
738  return format (s, "%cNaN", sign ? '-' : '+');
739 
740  /* Check for infinity. */
741  if (isinf (x))
742  return format (s, "%cinfinity", sign ? '-' : '+');
743 
744  x = normalize (x, &expon, &prec);
745 
746  /* Not enough digits to print anything: so just print 0 */
747  if ((word) - expon > (word) n_fraction_digits
748  && (output_style == 'f' || (output_style == 'g')))
749  goto do_zero;
750 
751  if (sign)
752  vec_add1 (s, '-');
753 
754  if (output_style == 'f'
755  || (output_style == 'g' && expon > -10 && expon < 10))
756  {
757  if (expon < 0)
758  {
759  /* Add decimal point and leading zeros. */
760  vec_add1 (s, '.');
761  n_fraction_done = clib_min (-(expon + 1), n_fraction_digits);
762  s = add_some_zeros (s, n_fraction_done);
763  decimal_point = -n_fraction_done;
764  added_decimal_point = 1;
765  }
766  else
767  decimal_point = expon + 1;
768  }
769  else
770  {
771  /* Exponential output style. */
772  decimal_point = 1;
773  output_style = 'e';
774  }
775 
776  while (1)
777  {
778  uword digit;
779 
780  /* Number is smaller than precision: call it zero. */
781  if (x < prec)
782  break;
783 
784  digit = x;
785  x -= digit;
786  if (x + prec >= 1)
787  {
788  digit++;
789  x -= 1;
790  }
791 
792  /* Round last printed digit. */
793  if (decimal_point <= 0
794  && n_fraction_done + 1 == n_fraction_digits && digit < 9)
795  digit += x >= .5;
796 
797  vec_add1 (s, '0' + digit);
798 
799  /* Move rightwards towards/away from decimal point. */
800  decimal_point--;
801 
802  n_fraction_done += decimal_point < 0;
803  if (decimal_point <= 0 && n_fraction_done >= n_fraction_digits)
804  break;
805 
806  if (decimal_point == 0 && x != 0)
807  {
808  vec_add1 (s, '.');
809  added_decimal_point = 1;
810  }
811 
812  x *= 10;
813  prec *= 10;
814  }
815 
816 done:
817  if (decimal_point > 0)
818  {
819  s = add_some_zeros (s, decimal_point);
820  decimal_point = 0;
821  }
822 
823  if (n_fraction_done < n_fraction_digits)
824  {
825  if (!added_decimal_point)
826  vec_add1 (s, '.');
827  s = add_some_zeros (s, n_fraction_digits - n_fraction_done);
828  }
829 
830  if (output_style == 'e')
831  s = format (s, "e%wd", expon);
832 
833  return s;
834 }
835 
836 
837 /*
838  * fd.io coding-style-patch-verification: ON
839  *
840  * Local Variables:
841  * eval: (c-set-style "gnu")
842  * End:
843  */
os.h
tmp
u32 * tmp
Definition: interface_output.c:1096
vec_add
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:688
va_fformat
__clib_export word va_fformat(FILE *f, char *fmt, va_list *va)
Definition: format.c:442
do_percent
static const u8 * do_percent(u8 **_s, const u8 *fmt, va_list *va)
Definition: format.c:155
format_info_t::justify
uword justify
Definition: format.c:90
fformat_append_cr
__clib_export void fformat_append_cr(FILE *ofp, const char *fmt,...)
Definition: format.c:480
format_info_t::how_long
uword how_long
Definition: format.c:97
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
format_integer_options_t::base
u8 base
Definition: format.c:70
string.h
f64_down
#define f64_down(f, sign, expon, fraction)
Definition: format.c:565
justify
static u8 * justify(u8 *s, format_info_t *fi, uword s_len_orig)
Definition: format.c:104
va_format
__clib_export u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:391
normalize
static f64 normalize(f64 x, word *expon_return, f64 *prec_return)
Definition: format.c:650
number
const char *const const double number
Definition: cJSON.h:268
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
format_integer_options_t::uppercase_digits
u8 uppercase_digits
Definition: format.c:79
i64
signed long i64
Definition: types.h:78
add_some_zeros
static u8 * add_some_zeros(u8 *s, uword n_zeros)
Definition: format.c:694
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
math.h
len
u8 len
Definition: ip_types.api:103
error.h
format_integer_options_t
Definition: format.c:67
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
BITS
#define BITS(x)
Definition: clib.h:69
c
svmdb_client_t * c
Definition: vpp_get_metrics.c:48
format_info_t
Definition: format.c:87
uword
u64 uword
Definition: types.h:112
f64
double f64
Definition: types.h:142
isinf
#define isinf(x)
Definition: math.h:60
format.h
format_info_t::width
uword width[2]
Definition: format.c:94
format_info_t::pad_char
uword pad_char
Definition: format.c:100
clib_min
#define clib_min(x, y)
Definition: clib.h:342
format
__clib_export u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:428
fmt
int cJSON_bool fmt
Definition: cJSON.h:160
format_integer
static u8 * format_integer(u8 *s, u64 number, format_integer_options_t *options)
Definition: format.c:509
format_float
static u8 * format_float(u8 *s, f64 x, uword n_digits_to_print, uword output_style)
Definition: format.c:707
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
f64_precision
static f64 f64_precision(int base2_expon)
Definition: format.c:600
u64
unsigned long u64
Definition: types.h:89
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
format_integer_options_t::n_bits
u8 n_bits
Definition: format.c:73
fdformat
__clib_export word fdformat(int fd, char *fmt,...)
Definition: format.c:491
u32
unsigned int u32
Definition: types.h:88
options
static struct option options[]
Definition: main.c:52
n_left
u32 n_left
Definition: interface_output.c:1096
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
fformat
__clib_export word fformat(FILE *f, char *fmt,...)
Definition: format.c:466
vec.h
times_power_of_ten
static f64 times_power_of_ten(f64 x, int n)
Definition: format.c:623
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
format_integer_options_t::is_signed
u8 is_signed
Definition: format.c:76
u8
unsigned char u8
Definition: types.h:56
i
int i
Definition: flowhash_template.h:376
word
i64 word
Definition: types.h:111
f64_up
static f64 f64_up(uword sign, word expon, u64 fraction)
Definition: format.c:576
mem.h
isnan
#define isnan(x)
Definition: math.h:56
os_puts
void os_puts(u8 *string, uword length, uword is_error)
Definition: unix-misc.c:192
vec_insert
#define vec_insert(V, N, M)
Insert N vector elements starting at element M, initialize new elements to zero (no header,...
Definition: vec.h:775