Something went wrong. Try again.
A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
Something went wrong. Try again.
7.8 kB · 323 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Copyright (C) 2002 by Gary Czvitkovicz * Copyright (C) 2017 by William Wilgus * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/
#include <stdarg.h>#include <stdbool.h>#include <limits.h>#include <string.h>#include "file.h"#include "format.h"
static const char hexdigit[] = "0123456789ABCDEF";
/* smaller compressed binary without inline but 18% slower */#define FMT_DECL static inline
FMT_DECL int fmt_width_precision(int *ch, const char **fmt, char **str, va_list *ap){ int value = 0; (void) str; (void) ap;
while (*ch >= '0' && *ch <= '9') { value = 10 * value + (*ch - '0'); *ch = *(*fmt)++; } return value;}
FMT_DECL int fmt_integer_signed(int *ch, const char **fmt, char **str, va_list *ap){ int val, rem, sign; (void) ch; (void) fmt;
val = sign = va_arg(*ap, int); if (val < 0) val = -val; do { rem = val % 10; val /= 10; *--(*str) = rem + '0';
} while (val > 0);
if (sign < 0) *--(*str) = '-'; return 0;}
FMT_DECL int fmt_integer_unsigned(int *ch, const char **fmt, char **str, va_list *ap){ unsigned int uval, urem; (void) ch; (void) fmt;
uval = va_arg(*ap, unsigned int); do { urem = uval % 10; uval /= 10; *--(*str) = urem + '0'; } while (uval > 0); return 0;}
FMT_DECL int fmt_long(int *ch, const char **fmt, char **str, va_list *ap){ int pad = 0; long lval, lrem, lsign = 0; unsigned long ulval, ulrem; char ch_l = *ch;
*ch = *(*fmt)++; if (*ch == 'd') { lval = lsign = va_arg(*ap, long);
if (lval < 0) lval = -lval; do { lrem = lval % 10; lval /= 10; *--(*str) = lrem + '0'; } while (lval > 0);
if (lsign < 0) *--(*str) = '-'; } else if (*ch == 'u') { ulval = va_arg(*ap, unsigned long); do { ulrem = ulval % 10; ulval /= 10; *--(*str) = ulrem + '0'; } while (ulval > 0); } else if (*ch == 'x' || *ch == 'X') { pad++; ulval = va_arg(*ap, long); do { *--(*str) = hexdigit[ulval & 0xf]; ulval >>= 4; } while (ulval > 0); } else { *--(*str) = ch_l; *--(*str) = *ch; } return pad;}
FMT_DECL int fmt_character(int *ch, const char **fmt, char **str, va_list *ap){ (void) ch; (void) fmt;
*--(*str) = va_arg(*ap, int); return 0;}
FMT_DECL int fmt_string(int *ch, const char **fmt, char **str, va_list *ap){ (void) ch; (void) fmt;
*str = va_arg (*ap, char*); return 0;}
FMT_DECL int fmt_hex_unsigned(int *ch, const char **fmt, char **str, va_list *ap){ unsigned int uval; (void) ch; (void) fmt;
uval = va_arg(*ap, int); do { *--(*str) = hexdigit[uval & 0xf]; uval >>= 4; } while (uval > 0); return 1;}
FMT_DECL int fmt_pointer(int *ch, const char **fmt, char **str, va_list *ap){ int pad = fmt_hex_unsigned(ch, fmt, str, ap); /* for pointers prepend 0x and act like 'X' */ *--(*str) = 'x'; *--(*str) = '0'; return pad;}
FMT_DECL int fmt_sizet(int *ch, const char **fmt, char **str, va_list *ap){ size_t uszval, uszrem; ssize_t szval, szrem, szsign; char ch_z = *ch; *ch = *(*fmt)++;
if (*ch == 'd') { szval = szsign = va_arg(*ap, ssize_t); if (szval < 0) szval = -szval; do { szrem = szval % 10; szval /= 10; *--(*str) = szrem + '0'; } while (szval > 0);
if (szsign < 0) *--(*str) = '-'; } else if (*ch == 'u') { uszval = va_arg(*ap, size_t); do { uszrem = uszval % 10; uszval /= 10; *--(*str) = uszrem + '0'; } while (uszval > 0); } else { *--(*str) = ch_z; *--(*str) = *ch; } return 0;}
static inline int fmt_next_char(int *ch, const char **fmt, char **str, va_list *ap){ (void) fmt; (void) ap;
*--(*str) = *ch; return 0;}
void format( /* call 'push()' for each output letter */ int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap){ bool ok = true; char *str; char tmpbuf[12], pad; int ch, width, precision, padded;
ch = *fmt++; tmpbuf[sizeof tmpbuf - 1] = '\0';
do { if (ch == '%') { str = tmpbuf + sizeof tmpbuf - 1; ch = *fmt++; padded = (ch == '0' ? 1 : 0); width = fmt_width_precision(&ch, &fmt, &str, &ap);
precision = INT_MAX; if(ch == '.') { ch = *fmt++; precision = fmt_width_precision(&ch, &fmt, &str, &ap); }
if (ch == 'd') fmt_integer_signed(&ch, &fmt, &str, &ap); else if (ch == 'u') fmt_integer_unsigned(&ch, &fmt, &str, &ap); else if (ch == 'l') padded += fmt_long(&ch, &fmt, &str, &ap); else if (ch == 'c') fmt_character(&ch, &fmt, &str, &ap); else if (ch == 's') fmt_string(&ch, &fmt, &str, &ap); else if (ch == 'x' || ch == 'X') padded += fmt_hex_unsigned(&ch, &fmt, &str, &ap); else if (ch == 'p' || ch == 'P') padded += fmt_pointer(&ch, &fmt, &str, &ap);#if 0 else if (ch == 'z') fmt_sizet(&ch, &fmt, &str, &ap);#endif else fmt_next_char(&ch, &fmt, &str, &ap);
width -= strlen (str); if (width > 0) { pad = (padded ? '0' : ' '); while (width-- > 0 && ok) ok=push(userp, pad); } while(*str != '\0' && ok && precision--) ok=push(userp, *str++); } else ok=push(userp, ch);
} while ((ch = *fmt++) != '\0' && ok);}
struct for_fprintf { int fd; /* where to store it */ int bytes; /* amount stored */};
static int fprfunc(void *pr, unsigned char letter){ struct for_fprintf *fpr = (struct for_fprintf *)pr; int rc = write(fpr->fd, &letter, 1);
if(rc > 0) { fpr->bytes++; /* count them */ return true; /* we are ok */ }
return false; /* failure */}
int fdprintf(int fd, const char *fmt, ...){ va_list ap; struct for_fprintf fpr;
fpr.fd=fd; fpr.bytes=0;
va_start(ap, fmt); format(fprfunc, &fpr, fmt, ap); va_end(ap);
return fpr.bytes; /* return 0 on error */}
void vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap){ format(push, userp, fmt, ap);}