aboutsummaryrefslogtreecommitdiffstats
path: root/vppinfra/vppinfra/format.c
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2016-12-19 23:05:39 +0100
committerDamjan Marion <damarion@cisco.com>2016-12-28 12:25:14 +0100
commit7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 (patch)
tree5de62f8dbd3a752f5a676ca600e43d2652d1ff1a /vppinfra/vppinfra/format.c
parent696f1adec0df3b8f161862566dd9c86174302658 (diff)
Reorganize source tree to use single autotools instance
Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23 Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'vppinfra/vppinfra/format.c')
-rw-r--r--vppinfra/vppinfra/format.c814
1 files changed, 0 insertions, 814 deletions
diff --git a/vppinfra/vppinfra/format.c b/vppinfra/vppinfra/format.c
deleted file mode 100644
index 78e52e9a2ad..00000000000
--- a/vppinfra/vppinfra/format.c
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*------------------------------------------------------------------
- * format.c -- see notice below
- *
- * October 2003, Eliot Dresselhaus
- *
- * Modifications to this file Copyright (c) 2003 by cisco Systems, Inc.
- * All rights reserved.
- *------------------------------------------------------------------
- */
-
-/*
- Copyright (c) 2001, 2002, 2003, 2006 Eliot Dresselhaus
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include <stdarg.h> /* va_start, etc */
-
-#ifdef CLIB_UNIX
-#include <unistd.h>
-#include <stdio.h>
-#endif
-
-#ifdef CLIB_STANDALONE
-#include <vppinfra/standalone_stdio.h>
-#endif
-
-#include <vppinfra/mem.h>
-#include <vppinfra/format.h>
-#include <vppinfra/vec.h>
-#include <vppinfra/error.h>
-#include <vppinfra/string.h>
-#include <vppinfra/os.h> /* os_puts */
-
-typedef struct
-{
- /* Output number in this base. */
- u8 base;
-
- /* Number of show of 64 bit number. */
- u8 n_bits;
-
- /* Signed or unsigned. */
- u8 is_signed;
-
- /* Output digits uppercase (not lowercase) %X versus %x. */
- u8 uppercase_digits;
-} format_integer_options_t;
-
-static u8 *format_integer (u8 * s, u64 number,
- format_integer_options_t * options);
-static u8 *format_float (u8 * s, f64 x, uword n_digits_to_print,
- uword output_style);
-
-typedef struct
-{
- /* String justification: + => right, - => left, = => center. */
- uword justify;
-
- /* Width of string (before and after decimal point for numbers).
- 0 => natural width. */
- uword width[2];
-
- /* Long => 'l', long long 'L', int 0. */
- uword how_long;
-
- /* Pad character. Defaults to space. */
- uword pad_char;
-} format_info_t;
-
-static u8 *
-justify (u8 * s, format_info_t * fi, uword s_len_orig)
-{
- uword i0, l0, l1;
-
- i0 = s_len_orig;
- l0 = i0 + fi->width[0];
- l1 = vec_len (s);
-
- /* If width is zero user returned width. */
- if (l0 == i0)
- l0 = l1;
-
- if (l1 > l0)
- _vec_len (s) = l0;
- else if (l0 > l1)
- {
- uword n = l0 - l1;
- uword n_left = 0, n_right = 0;
-
- switch (fi->justify)
- {
- case '-':
- n_right = n;
- break;
-
- case '+':
- n_left = n;
- break;
-
- case '=':
- n_right = n_left = n / 2;
- if (n % 2)
- n_left++;
- break;
- }
- if (n_left > 0)
- {
- vec_insert (s, n_left, i0);
- memset (s + i0, fi->pad_char, n_left);
- l1 = vec_len (s);
- }
- if (n_right > 0)
- {
- vec_resize (s, n_right);
- memset (s + l1, fi->pad_char, n_right);
- }
- }
- return s;
-}
-
-static u8 *
-do_percent (u8 ** _s, u8 * fmt, va_list * va)
-{
- u8 *s = *_s;
- uword c;
-
- u8 *f = fmt;
-
- format_info_t fi = {
- .justify = '+',
- .width = {0},
- .pad_char = ' ',
- .how_long = 0,
- };
-
- uword i;
-
- ASSERT (f[0] == '%');
-
- switch (c = *++f)
- {
- case '%':
- /* %% => % */
- vec_add1 (s, c);
- f++;
- goto done;
-
- case '-':
- case '+':
- case '=':
- fi.justify = c;
- c = *++f;
- break;
- }
-
- /* Parse width0 . width1. */
- {
- uword is_first_digit = 1;
-
- fi.width[0] = fi.width[1] = 0;
- for (i = 0; i < 2; i++)
- {
- if (c == '0' && i == 0 && is_first_digit)
- fi.pad_char = '0';
- is_first_digit = 0;
- if (c == '*')
- {
- fi.width[i] = va_arg (*va, int);
- c = *++f;
- }
- else
- {
- while (c >= '0' && c <= '9')
- {
- fi.width[i] = 10 * fi.width[i] + (c - '0');
- c = *++f;
- }
- }
- if (c != '.')
- break;
- c = *++f;
- }
- }
-
- /* Parse %l* and %L* */
- switch (c)
- {
- case 'w':
- /* word format. */
- fi.how_long = 'w';
- c = *++f;
- break;
-
- case 'L':
- case 'l':
- fi.how_long = c;
- c = *++f;
- if (c == 'l' && *f == 'l')
- {
- fi.how_long = 'L';
- c = *++f;
- }
- break;
- }
-
- /* Finally we are ready for format letter. */
- if (c != 0)
- {
- uword s_initial_len = vec_len (s);
- format_integer_options_t o = {
- .is_signed = 0,
- .base = 10,
- .n_bits = BITS (uword),
- .uppercase_digits = 0,
- };
-
- f++;
-
- switch (c)
- {
- default:
- {
- /* Try to give a helpful error message. */
- vec_free (s);
- s = format (s, "**** CLIB unknown format `%%%c' ****", c);
- goto done;
- }
-
- case 'c':
- vec_add1 (s, va_arg (*va, int));
- break;
-
- case 'p':
- vec_add1 (s, '0');
- vec_add1 (s, 'x');
-
- o.is_signed = 0;
- o.n_bits = BITS (uword *);
- o.base = 16;
- o.uppercase_digits = 0;
-
- s = format_integer (s, pointer_to_uword (va_arg (*va, void *)), &o);
- break;
-
- case 'x':
- case 'X':
- case 'u':
- case 'd':
- {
- u64 number;
-
- o.base = 10;
- if (c == 'x' || c == 'X')
- o.base = 16;
- o.is_signed = c == 'd';
- o.uppercase_digits = c == 'X';
-
- switch (fi.how_long)
- {
- case 'L':
- number = va_arg (*va, unsigned long long);
- o.n_bits = BITS (unsigned long long);
- break;
-
- case 'l':
- number = va_arg (*va, long);
- o.n_bits = BITS (long);
- break;
-
- case 'w':
- number = va_arg (*va, word);
- o.n_bits = BITS (uword);
- break;
-
- default:
- number = va_arg (*va, int);
- o.n_bits = BITS (int);
- break;
- }
-
- s = format_integer (s, number, &o);
- }
- break;
-
- case 's':
- case 'S':
- {
- char *cstring = va_arg (*va, char *);
- uword len;
-
- if (!cstring)
- {
- cstring = "(nil)";
- len = 5;
- }
- else if (fi.width[1] != 0)
- len = clib_min (strlen (cstring), fi.width[1]);
- else
- len = strlen (cstring);
-
- /* %S => format string as C identifier (replace _ with space). */
- if (c == 'S')
- {
- for (i = 0; i < len; i++)
- vec_add1 (s, cstring[i] == '_' ? ' ' : cstring[i]);
- }
- else
- vec_add (s, cstring, len);
- }
- break;
-
- case 'v':
- {
- u8 *v = va_arg (*va, u8 *);
- uword len;
-
- if (fi.width[1] != 0)
- len = clib_min (vec_len (v), fi.width[1]);
- else
- len = vec_len (v);
-
- vec_add (s, v, len);
- }
- break;
-
- case 'f':
- case 'g':
- case 'e':
- /* Floating point. */
- ASSERT (fi.how_long == 0 || fi.how_long == 'l');
- s = format_float (s, va_arg (*va, double), fi.width[1], c);
- break;
-
- case 'U':
- /* User defined function. */
- {
- typedef u8 *(user_func_t) (u8 * s, va_list * args);
- user_func_t *u = va_arg (*va, user_func_t *);
-
- s = (*u) (s, va);
- }
- break;
- }
-
- s = justify (s, &fi, s_initial_len);
- }
-
-done:
- *_s = s;
- return f;
-}
-
-u8 *
-va_format (u8 * s, const char *fmt, va_list * va)
-{
- u8 *f = (u8 *) fmt, *g;
- u8 c;
-
- g = f;
- while (1)
- {
- c = *f;
-
- if (!c)
- break;
-
- if (c == '%')
- {
- if (f > g)
- vec_add (s, g, f - g);
- f = g = do_percent (&s, f, va);
- }
- else
- {
- f++;
- }
- }
-
- if (f > g)
- vec_add (s, g, f - g);
-
- return s;
-}
-
-u8 *
-format (u8 * s, const char *fmt, ...)
-{
- va_list va;
- va_start (va, fmt);
- s = va_format (s, fmt, &va);
- va_end (va);
- return s;
-}
-
-word
-va_fformat (FILE * f, char *fmt, va_list * va)
-{
- word ret;
- u8 *s;
-
- s = va_format (0, fmt, va);
-
-#ifdef CLIB_UNIX
- if (f)
- {
- ret = fwrite (s, vec_len (s), 1, f);
- }
- else
-#endif /* CLIB_UNIX */
- {
- ret = 0;
- os_puts (s, vec_len (s), /* is_error */ 0);
- }
-
- vec_free (s);
- return ret;
-}
-
-word
-fformat (FILE * f, char *fmt, ...)
-{
- va_list va;
- word ret;
-
- va_start (va, fmt);
- ret = va_fformat (f, fmt, &va);
- va_end (va);
-
- return (ret);
-}
-
-#ifdef CLIB_UNIX
-word
-fdformat (int fd, char *fmt, ...)
-{
- word ret;
- u8 *s;
- va_list va;
-
- va_start (va, fmt);
- s = va_format (0, fmt, &va);
- va_end (va);
-
- ret = write (fd, s, vec_len (s));
- vec_free (s);
- return ret;
-}
-#endif
-
-/* Format integral type. */
-static u8 *
-format_integer (u8 * s, u64 number, format_integer_options_t * options)
-{
- u64 q;
- u32 r;
- u8 digit_buffer[128];
- u8 *d = digit_buffer + sizeof (digit_buffer);
- word c, base;
-
- if (options->is_signed && (i64) number < 0)
- {
- number = -number;
- vec_add1 (s, '-');
- }
-
- if (options->n_bits < BITS (number))
- number &= ((u64) 1 << options->n_bits) - 1;
-
- base = options->base;
-
- while (1)
- {
- q = number / base;
- r = number % base;
-
- if (r < 10 + 26 + 26)
- {
- if (r < 10)
- c = '0' + r;
- else if (r < 10 + 26)
- c = 'a' + (r - 10);
- else
- c = 'A' + (r - 10 - 26);
-
- if (options->uppercase_digits
- && base <= 10 + 26 && c >= 'a' && c <= 'z')
- c += 'A' - 'a';
-
- *--d = c;
- }
- else /* will never happen, warning be gone */
- {
- *--d = '?';
- }
-
- if (q == 0)
- break;
-
- number = q;
- }
-
- vec_add (s, d, digit_buffer + sizeof (digit_buffer) - d);
- return s;
-}
-
-/* Floating point formatting. */
-/* Deconstruct IEEE 64 bit number into sign exponent and fraction. */
-#define f64_down(f,sign,expon,fraction) \
-do { \
- union { u64 u; f64 f; } _f64_down_tmp; \
- _f64_down_tmp.f = (f); \
- (sign) = (_f64_down_tmp.u >> 63); \
- (expon) = ((_f64_down_tmp.u >> 52) & 0x7ff) - 1023; \
- (fraction) = ((_f64_down_tmp.u << 12) >> 12) | ((u64) 1 << 52); \
-} while (0)
-
-/* Construct IEEE 64 bit number. */
-static f64
-f64_up (uword sign, word expon, u64 fraction)
-{
- union
- {
- u64 u;
- f64 f;
- } tmp;
-
- tmp.u = (u64) ((sign) != 0) << 63;
-
- expon += 1023;
- if (expon > 1023)
- expon = 1023;
- if (expon < 0)
- expon = 0;
- tmp.u |= (u64) expon << 52;
-
- tmp.u |= fraction & (((u64) 1 << 52) - 1);
-
- return tmp.f;
-}
-
-/* Returns approximate precision of number given its exponent. */
-static f64
-f64_precision (int base2_expon)
-{
- static int n_bits = 0;
-
- if (!n_bits)
- {
- /* Compute number of significant bits in floating point representation. */
- f64 one = 0;
- f64 small = 1;
-
- while (one != 1)
- {
- small *= .5;
- n_bits++;
- one = 1 + small;
- }
- }
-
- return f64_up (0, base2_expon - n_bits, 0);
-}
-
-/* Return x 10^n */
-static f64
-times_power_of_ten (f64 x, int n)
-{
- if (n >= 0)
- {
- static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, };
- while (n >= 8)
- {
- x *= 1e+8;
- n -= 8;
- }
- return x * t[n];
- }
- else
- {
- static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, };
- while (n <= -8)
- {
- x *= 1e-8;
- n += 8;
- }
- return x * t[-n];
- }
-
-}
-
-/* Write x = y * 10^expon with 1 < y < 10. */
-static f64
-normalize (f64 x, word * expon_return, f64 * prec_return)
-{
- word expon2, expon10;
- CLIB_UNUSED (u64 fraction);
- CLIB_UNUSED (word sign);
- f64 prec;
-
- f64_down (x, sign, expon2, fraction);
-
- expon10 =
- .5 +
- expon2 * .301029995663981195213738894724493 /* Log (2) / Log (10) */ ;
-
- prec = f64_precision (expon2);
- x = times_power_of_ten (x, -expon10);
- prec = times_power_of_ten (prec, -expon10);
-
- while (x < 1)
- {
- x *= 10;
- prec *= 10;
- expon10--;
- }
-
- while (x > 10)
- {
- x *= .1;
- prec *= .1;
- expon10++;
- }
-
- if (x + prec >= 10)
- {
- x = 1;
- expon10++;
- }
-
- *expon_return = expon10;
- *prec_return = prec;
-
- return x;
-}
-
-static u8 *
-add_some_zeros (u8 * s, uword n_zeros)
-{
- while (n_zeros > 0)
- {
- vec_add1 (s, '0');
- n_zeros--;
- }
- return s;
-}
-
-/* Format a floating point number with the given number of fractional
- digits (e.g. 1.2345 with 2 fraction digits yields "1.23") and output style. */
-static u8 *
-format_float (u8 * s, f64 x, uword n_fraction_digits, uword output_style)
-{
- f64 prec;
- word sign, expon, n_fraction_done, added_decimal_point;
- /* Position of decimal point relative to where we are. */
- word decimal_point;
-
- /* Default number of digits to print when its not specified. */
- if (n_fraction_digits == ~0)
- n_fraction_digits = 7;
- n_fraction_done = 0;
- decimal_point = 0;
- added_decimal_point = 0;
- sign = expon = 0;
-
- /* Special case: zero. */
- if (x == 0)
- {
- do_zero:
- vec_add1 (s, '0');
- goto done;
- }
-
- if (x < 0)
- {
- x = -x;
- sign = 1;
- }
-
- /* Check for infinity. */
- if (x == x / 2)
- return format (s, "%cinfinity", sign ? '-' : '+');
-
- x = normalize (x, &expon, &prec);
-
- /* Not enough digits to print anything: so just print 0 */
- if ((word) - expon > (word) n_fraction_digits
- && (output_style == 'f' || (output_style == 'g')))
- goto do_zero;
-
- if (sign)
- vec_add1 (s, '-');
-
- if (output_style == 'f'
- || (output_style == 'g' && expon > -10 && expon < 10))
- {
- if (expon < 0)
- {
- /* Add decimal point and leading zeros. */
- vec_add1 (s, '.');
- n_fraction_done = clib_min (-(expon + 1), n_fraction_digits);
- s = add_some_zeros (s, n_fraction_done);
- decimal_point = -n_fraction_done;
- added_decimal_point = 1;
- }
- else
- decimal_point = expon + 1;
- }
- else
- {
- /* Exponential output style. */
- decimal_point = 1;
- output_style = 'e';
- }
-
- while (1)
- {
- uword digit;
-
- /* Number is smaller than precision: call it zero. */
- if (x < prec)
- break;
-
- digit = x;
- x -= digit;
- if (x + prec >= 1)
- {
- digit++;
- x -= 1;
- }
-
- /* Round last printed digit. */
- if (decimal_point <= 0
- && n_fraction_done + 1 == n_fraction_digits && digit < 9)
- digit += x >= .5;
-
- vec_add1 (s, '0' + digit);
-
- /* Move rightwards towards/away from decimal point. */
- decimal_point--;
-
- n_fraction_done += decimal_point < 0;
- if (decimal_point <= 0 && n_fraction_done >= n_fraction_digits)
- break;
-
- if (decimal_point == 0 && x != 0)
- {
- vec_add1 (s, '.');
- added_decimal_point = 1;
- }
-
- x *= 10;
- prec *= 10;
- }
-
-done:
- if (decimal_point > 0)
- {
- s = add_some_zeros (s, decimal_point);
- decimal_point = 0;
- }
-
- if (n_fraction_done < n_fraction_digits)
- {
- if (!added_decimal_point)
- vec_add1 (s, '.');
- s = add_some_zeros (s, n_fraction_digits - n_fraction_done);
- }
-
- if (output_style == 'e')
- s = format (s, "e%wd", expon);
-
- return s;
-}
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */