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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
15 /*------------------------------------------------------------------
16 * format.c -- see notice below
18 * October 2003, Eliot Dresselhaus
20 * Modifications to this file Copyright (c) 2003 by cisco Systems, Inc.
21 * All rights reserved.
22 *------------------------------------------------------------------
26 Copyright (c) 2001, 2002, 2003, 2006 Eliot Dresselhaus
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:
36 The above copyright notice and this permission notice shall be
37 included in all copies or substantial portions of the Software.
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.
48 #include <stdarg.h> /* va_start, etc */
55 #ifdef CLIB_STANDALONE
56 #include <vppinfra/standalone_stdio.h>
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 */
67 /* Output number in this base. */
70 /* Number of show of 64 bit number. */
73 /* Signed or unsigned. */
76 /* Output digits uppercase (not lowercase) %X versus %x. */
78 } format_integer_options_t;
80 static u8 * format_integer (u8 * s, u64 number, format_integer_options_t * options);
81 static u8 * format_float (u8 * s, f64 x, uword n_digits_to_print, uword output_style);
84 /* String justification: + => right, - => left, = => center. */
87 /* Width of string (before and after decimal point for numbers).
88 0 => natural width. */
91 /* Long => 'l', long long 'L', int 0. */
94 /* Pad character. Defaults to space. */
98 static u8 * justify (u8 * s, format_info_t * fi, uword s_len_orig)
103 l0 = i0 + fi->width[0];
106 /* If width is zero user returned width. */
115 uword n_left = 0, n_right = 0;
128 n_right = n_left = n/2;
135 vec_insert (s, n_left, i0);
136 memset (s + i0, fi->pad_char, n_left);
141 vec_resize (s, n_right);
142 memset (s + l1, fi->pad_char, n_right);
148 static u8 * do_percent (u8 ** _s, u8 * fmt, va_list * va)
164 ASSERT (f[0] == '%');
182 /* Parse width0 . width1. */
184 uword is_first_digit = 1;
186 fi.width[0] = fi.width[1] = 0;
187 for (i = 0; i < 2; i++)
189 if (c == '0' && i == 0 && is_first_digit)
193 fi.width[i] = va_arg(*va, int);
196 while (c >= '0' && c <= '9') {
197 fi.width[i] = 10*fi.width[i] + (c - '0');
207 /* Parse %l* and %L* */
220 if (c == 'l' && *f == 'l')
228 /* Finally we are ready for format letter. */
231 uword s_initial_len = vec_len (s);
232 format_integer_options_t o = {
235 .n_bits = BITS (uword),
236 .uppercase_digits = 0,
244 /* Try to give a helpful error message. */
246 s = format (s, "**** CLIB unknown format `%%%c' ****", c);
251 vec_add1 (s, va_arg (*va, int));
259 o.n_bits = BITS (uword *);
261 o.uppercase_digits = 0;
263 s = format_integer (s, pointer_to_uword (va_arg (*va, void *)), &o);
274 if (c == 'x' || c == 'X')
276 o.is_signed = c == 'd';
277 o.uppercase_digits = c == 'X';
282 number = va_arg (*va, unsigned long long);
283 o.n_bits = BITS (unsigned long long);
287 number = va_arg (*va, long);
288 o.n_bits = BITS (long);
292 number = va_arg (*va, word);
293 o.n_bits = BITS (uword);
297 number = va_arg (*va, int);
298 o.n_bits = BITS (int);
302 s = format_integer (s, number, &o);
309 char * cstring = va_arg (*va, char *);
317 else if (fi.width[1] != 0)
318 len = clib_min (strlen (cstring), fi.width[1]);
320 len = strlen (cstring);
322 /* %S => format string as C identifier (replace _ with space). */
325 for (i = 0; i < len; i++)
326 vec_add1 (s, cstring[i] == '_' ? ' ' : cstring[i]);
329 vec_add (s, cstring, len);
335 u8 * v = va_arg (*va, u8 *);
338 if (fi.width[1] != 0)
339 len = clib_min (vec_len (v), fi.width[1]);
347 case 'f': case 'g': case 'e':
348 /* Floating point. */
349 ASSERT (fi.how_long == 0 || fi.how_long == 'l');
351 va_arg (*va, double),
356 /* User defined function. */
358 typedef u8 * (user_func_t) (u8 * s, va_list * args);
359 user_func_t * u = va_arg (*va, user_func_t *);
366 s = justify (s, &fi, s_initial_len);
374 u8 * va_format (u8 * s, char * fmt, va_list * va)
376 u8 * f = (u8 *) fmt, * g;
390 vec_add (s, g, f - g);
391 f = g = do_percent (&s, f, va);
400 vec_add (s, g, f - g);
405 u8 * format (u8 * s, char * fmt, ...)
409 s = va_format (s, fmt, &va);
414 word va_fformat (FILE * f, char * fmt, va_list * va)
419 s = va_format (0, fmt, va);
424 ret = fwrite (s, vec_len (s), 1, f);
427 #endif /* CLIB_UNIX */
430 os_puts (s, vec_len (s), /* is_error */ 0);
437 word fformat (FILE * f, char * fmt, ...)
443 ret = va_fformat(f, fmt, &va);
450 word fdformat (int fd, char * fmt, ...)
457 s = va_format (0, fmt, &va);
460 ret = write (fd, s, vec_len (s));
466 /* Format integral type. */
467 static u8 * format_integer (u8 * s, u64 number, format_integer_options_t * options)
471 u8 digit_buffer[128];
472 u8 * d = digit_buffer + sizeof (digit_buffer);
475 if (options->is_signed && (i64) number < 0)
481 if (options->n_bits < BITS (number))
482 number &= ((u64) 1 << options->n_bits) - 1;
484 base = options->base;
498 c = 'A' + (r - 10 - 26);
500 if (options->uppercase_digits
502 && c >= 'a' && c <= 'z')
507 else /* will never happen, warning be gone */
518 vec_add (s, d, digit_buffer + sizeof (digit_buffer) - d);
522 /* Floating point formatting. */
523 /* Deconstruct IEEE 64 bit number into sign exponent and fraction. */
524 #define f64_down(f,sign,expon,fraction) \
526 union { u64 u; f64 f; } _f64_down_tmp; \
527 _f64_down_tmp.f = (f); \
528 (sign) = (_f64_down_tmp.u >> 63); \
529 (expon) = ((_f64_down_tmp.u >> 52) & 0x7ff) - 1023; \
530 (fraction) = ((_f64_down_tmp.u << 12) >> 12) | ((u64) 1 << 52); \
533 /* Construct IEEE 64 bit number. */
534 static f64 f64_up (uword sign, word expon, u64 fraction)
536 union { u64 u; f64 f; } tmp;
538 tmp.u = (u64) ((sign) != 0) << 63;
545 tmp.u |= (u64) expon << 52;
547 tmp.u |= fraction & (((u64) 1 << 52) - 1);
552 /* Returns approximate precision of number given its exponent. */
553 static f64 f64_precision (int base2_expon)
555 static int n_bits = 0;
559 /* Compute number of significant bits in floating point representation. */
571 return f64_up (0, base2_expon - n_bits, 0);
575 static f64 times_power_of_ten (f64 x, int n)
579 static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
589 static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
600 /* Write x = y * 10^expon with 1 < y < 10. */
601 static f64 normalize (f64 x, word * expon_return, f64 * prec_return)
603 word expon2, expon10;
604 CLIB_UNUSED (u64 fraction);
605 CLIB_UNUSED (word sign);
608 f64_down (x, sign, expon2, fraction);
610 expon10 = .5 + expon2 * .301029995663981195213738894724493 /* Log (2) / Log (10) */;
612 prec = f64_precision (expon2);
613 x = times_power_of_ten (x, -expon10);
614 prec = times_power_of_ten (prec, -expon10);
636 *expon_return = expon10;
642 static u8 * add_some_zeros (u8 * s, uword n_zeros)
652 /* Format a floating point number with the given number of fractional
653 digits (e.g. 1.2345 with 2 fraction digits yields "1.23") and output style. */
655 format_float (u8 * s, f64 x,
656 uword n_fraction_digits,
660 word sign, expon, n_fraction_done, added_decimal_point;
661 /* Position of decimal point relative to where we are. */
664 /* Default number of digits to print when its not specified. */
665 if (n_fraction_digits == ~0)
666 n_fraction_digits = 7;
669 added_decimal_point = 0;
672 /* Special case: zero. */
686 /* Check for infinity. */
688 return format (s, "%cinfinity", sign ? '-' : '+');
690 x = normalize (x, &expon, &prec);
692 /* Not enough digits to print anything: so just print 0 */
693 if ((word) -expon > (word) n_fraction_digits
694 && (output_style == 'f' || (output_style == 'g')))
700 if (output_style == 'f'
701 || (output_style == 'g' && expon > -10 && expon < 10))
705 /* Add decimal point and leading zeros. */
707 n_fraction_done = clib_min (-(expon + 1), n_fraction_digits);
708 s = add_some_zeros (s, n_fraction_done);
709 decimal_point = -n_fraction_done;
710 added_decimal_point = 1;
713 decimal_point = expon + 1;
717 /* Exponential output style. */
726 /* Number is smaller than precision: call it zero. */
738 /* Round last printed digit. */
739 if (decimal_point <= 0
740 && n_fraction_done + 1 == n_fraction_digits
744 vec_add1 (s, '0' + digit);
746 /* Move rightwards towards/away from decimal point. */
749 n_fraction_done += decimal_point < 0;
750 if (decimal_point <= 0
751 && n_fraction_done >= n_fraction_digits)
754 if (decimal_point == 0 && x != 0)
757 added_decimal_point = 1;
765 if (decimal_point > 0)
767 s = add_some_zeros (s, decimal_point);
771 if (n_fraction_done < n_fraction_digits)
773 if (! added_decimal_point)
775 s = add_some_zeros (s, n_fraction_digits - n_fraction_done);
778 if (output_style == 'e')
779 s = format (s, "e%wd", expon);