diff options
Diffstat (limited to 'hifi/xaf/hifi-dpf/core/util/tinyvprintf.c')
-rw-r--r-- | hifi/xaf/hifi-dpf/core/util/tinyvprintf.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/hifi/xaf/hifi-dpf/core/util/tinyvprintf.c b/hifi/xaf/hifi-dpf/core/util/tinyvprintf.c new file mode 100644 index 00000000..25d7e03e --- /dev/null +++ b/hifi/xaf/hifi-dpf/core/util/tinyvprintf.c @@ -0,0 +1,198 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, 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 <string.h> +#include "lib/tinyput.h" + + +/* + * Simple formatted output routine. + * Designed primarily for small size (and secondarily for efficiency). + * Only a common subset of printf formats and options are handled: + * + * %[-+ ][0][width]i decimal signed integer + * %[-+ ][0][width]d decimal signed integer + * %[-][0][width]u decimal unsigned integer + * %[-][0][width]x hex unsigned integer + * %[-][0][width]p hex unsigned integer with 0x prefix ("pointer") + * %[-][width]c single character + * %[-][width]s string + * + * These modifiers are ignored (legally on 32-bit Xtensa): + * # (alternate format) + * h (short) expands to int on 32-bit Xtensa + * l (long) same as int on 32-bit Xtensa + * j (intmax_t or uintmax_t) same as int on 32-bit Xtensa + * z (size_t or ssize_t) same as int on 32-bit Xtensa + * t (ptrdiff_t) same as int on 32-bit Xtensa + * + * Does NOT support: + * width.prec (precision modifier) + * %X (capitalized hex; handles this as lowercase hex) + * %o (octal) + * %[L][feEgG] (floating point formats) + * %a %A (hex floating point formats, C99) + * %C (multibyte character) + * %S (multibyte character string) + * %n (returning count of character written) + * ll (long long) + * q j z t (other size modifiers, eg. see glibc) + */ +int tiny_vsprintf(char *out, const char *fmt, va_list ap) +{ + int total = 0; + char c, space = ' ', buf[11]; /* largest 32-bit integer output (octal) */ + + while ((c = *(char*)fmt++) != 0) { + if (c != '%') { + *out++ = c; + total++; + } else { + int width = 0, len = 1, rightjust = 1; + unsigned n; + char *s = buf, *t, pad = ' ', sign = 0; + while (1) { + c = *(char*)fmt++; + switch (c) { + case 'c': buf[0] = va_arg(ap, int); goto donefmt; + case 's': s = va_arg(ap, char*); + if (s == 0) + len = 0; + else { + for (t = s; *t; t++) ; + len = t - s; + } + goto donefmt; + + case '#': /* ignore (not supported) */ + case 'h': /* ignore (short; passed as int) */ + case 'l': /* ignore (long; same as int) */ + case 'j': /* ignore (intmax_t or uintmax_t; same as int) */ + case 'z': /* ignore (size_t or ssize_t; same as int) */ + case 't': /* ignore (ptrdiff_t; same as int) */ + break; + + case ' ': sign = ' '; break; + case '+': sign = '+'; break; + case '-': rightjust = 0; break; + + case 'i': /*FALLTHROUGH*/ + case 'd': n = va_arg(ap, int); + if ((int)n < 0) { + sign = '-'; + n = -(int)n; + } + if (sign) { + if (rightjust && pad == ' ') + *s++ = sign; + else { + *out++ = sign; + width--; + total++; + } + } + goto do_decimal; + case 'u': n = va_arg(ap, int); + do_decimal: + { + /* (avoids division or multiplication) */ + int digit, i, seen = 0; + for (digit = 0; n >= 1000000000; digit++) + n -= 1000000000; + for (i = 9;;) { + if (!seen && digit != 0) + seen = i; + if (seen) + *s++ = '0' + digit; + for (digit = 0; n >= 100000000; digit++) + n -= 100000000; + if (--i == 0) { + *s++ = '0' + digit; + len = s - buf; + s = buf; + goto donefmt; + } + n = ((n << 1) + (n << 3)); + } + } + /*NOTREACHED*/ + +#if 0 + case 'o': n = va_arg(ap, unsigned); + s = buf + 11; + do { + *--s = '0' + (n & 7); + n = (unsigned)n >> 3; + } while (n); + len = buf + 11 - s; + goto donefmt; +#endif + + case 'p': *out++ = '0', *out++ = 'x'; + total += 2; + /*FALLTHROUGH*/ + case 'X': /*FALLTHROUGH*/ + case 'x': n = va_arg(ap, unsigned); + s = buf + 8; + do { + *--s = "0123456789abcdef"[n & 0xF]; + n = (unsigned)n >> 4; + } while (n); + len = buf + 8 - s; + goto donefmt; + + case 0: goto done; + case '0': if (width == 0) pad = '0'; /*FALLTHROUGH*/ + default: if (c >= '0' && c <= '9') + width = ((width<<1) + (width<<3)) + (c - '0'); + else { + buf[0] = c; /* handles case of '%' */ + goto donefmt; + } + } + } + /*NOTREACHED*/ + donefmt: + if (len < width) { + total += width; + if (rightjust) + do { *out++ = pad; } while (len < --width); + } else + total += len; + for(n = len; n > 0; n--) *out++ = *s++; + for (; len < width; len++) *out++ = space; + } + } +done: + return total; +} + +int tiny_sprintf(char *out, const char *fmt, ...) +{ + int n = 0; + va_list ap; + va_start(ap, fmt); + n = tiny_vsprintf(out, fmt, ap); + va_end(ap); + return n; +} |