Esempio n. 1
0
/**
 * Print a formatted string to a dynamically allocated buffer, using va_list
 *
 * @param strp Pointer for output string
 * @param fmt  Formatted string
 * @param ap   Variable-arguments list
 *
 * @return 0 if success, otherwise errorcode
 */
int re_vsdprintf(char **strp, const char *fmt, va_list ap)
{
	struct dyn_print dp;
	int err;

	if (!strp)
		return EINVAL;

	dp.size = 16;
	dp.str  = mem_alloc(dp.size, NULL);
	if (!dp.str)
		return ENOMEM;

	dp.p = dp.str;
	dp.l = dp.size;

	err = re_vhprintf(fmt, ap, print_handler_dyn, &dp);
	if (err)
		goto out;

	*dp.p = '\0';

 out:
	if (err)
		mem_deref(dp.str);
	else
		*strp = dp.str;

	return err;
}
Esempio n. 2
0
/**
 * Print a formatted string to a memory buffer
 *
 * @param mb  Memory buffer
 * @param fmt Formatted string
 *
 * @return 0 if success, otherwise errorcode
 */
int mbuf_printf(struct mbuf *mb, const char *fmt, ...)
{
	int err = 0;
	va_list ap;

	va_start(ap, fmt);
	err = re_vhprintf(fmt, ap, vprintf_handler, mb);
	va_end(ap);

	return err;
}
Esempio n. 3
0
/**
 * Print a formatted string
 *
 * @param pf  Print backend
 * @param fmt Formatted string
 *
 * @return 0 if success, otherwise errorcode
 */
int re_hprintf(struct re_printf *pf, const char *fmt, ...)
{
	va_list ap;
	int err;

	if (!pf)
		return EINVAL;

	va_start(ap, fmt);
	err = re_vhprintf(fmt, ap, pf->vph, pf->arg);
	va_end(ap);

	return err;
}
Esempio n. 4
0
/**
 * Print a formatted string to a buffer, using va_list
 *
 * @param str  Buffer for output string
 * @param size Size of buffer
 * @param fmt  Formatted string
 * @param ap   Variable-arguments list
 *
 * @return The number of characters printed, or -1 if error
 */
int re_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
{
	struct pl pl;
	int err;

	if (!str || !size)
		return -1;

	pl.p = str;
	pl.l = size - 1;

	err = re_vhprintf(fmt, ap, print_handler, &pl);

	str[size - pl.l - 1] = '\0';

	return err ? -1 : (int)(size - pl.l - 1);
}
Esempio n. 5
0
/**
 * Print a formatted string to a file stream, using va_list
 *
 * @param stream File stream for the output
 * @param fmt    Formatted string
 * @param ap     Variable-arguments list
 *
 * @return The number of characters printed, or -1 if error
 */
int re_vfprintf(FILE *stream, const char *fmt, va_list ap)
{
	char buf[4096]; /* TODO: avoid static, use print_handler_dyn ? */
	struct pl pl;
	size_t n;

	if (!stream)
		return -1;

	pl.p = buf;
	pl.l = sizeof(buf);

	if (0 != re_vhprintf(fmt, ap, print_handler, &pl))
		return -1;

	n = sizeof(buf) - pl.l;

	if (1 != fwrite(buf, n, 1, stream))
		return -1;

	return (int)n;
}
Esempio n. 6
0
/**
 * Print a formatted variable argument list to a memory buffer
 *
 * @param mb  Memory buffer
 * @param fmt Formatted string
 * @param ap  Variable argument list
 *
 * @return 0 if success, otherwise errorcode
 */
int mbuf_vprintf(struct mbuf *mb, const char *fmt, va_list ap)
{
	return re_vhprintf(fmt, ap, vprintf_handler, mb);
}
Esempio n. 7
0
/**
 * Print a formatted string
 *
 * @param fmt Formatted string
 * @param ap  Variable argument
 * @param vph Print handler
 * @param arg Handler argument
 *
 * @return 0 if success, otherwise errorcode
 *
 * Extensions:
 *
 * <pre>
 *   %b  (char *, size_t)        Buffer string with pointer and length
 *   %r  (struct pl)             Pointer-length object
 *   %w  (uint8_t *, size_t)     Binary buffer to hexadecimal format
 *   %j  (struct sa *)           Socket address - address part only
 *   %J  (struct sa *)           Socket address and port - like 1.2.3.4:1234
 *   %H  (re_printf_h *, void *) Print handler with argument
 *   %v  (char *fmt, va_list *)  Variable argument list
 *   %m  (int)                   Describe an error code
 * </pre>
 *
 * Reserved for the future:
 *
 *   %k
 *   %y
 *
 */
int re_vhprintf(const char *fmt, va_list ap, re_vprintf_h *vph, void *arg)
{
	uint8_t base, *bptr;
	char pch, ch, num[NUM_SIZE], addr[64], msg[256];
	enum length_modifier lenmod = LENMOD_NONE;
	struct re_printf pf;
	bool fm = false, plr = false;
	const struct pl *pl;
	size_t pad = 0, fpad = -1, len, i;
	const char *str, *p = fmt, *p0 = fmt;
	const struct sa *sa;
	re_printf_h *ph;
	void *ph_arg;
	va_list *apl;
	int err = 0;
	void *ptr;
	uint64_t n;
	int64_t sn;
	bool uc = false;
	double dbl;

	if (!fmt || !vph)
		return EINVAL;

	pf.vph = vph;
	pf.arg = arg;

	for (;*p && !err; p++) {

		if (!fm) {
			if (*p != '%')
				continue;

			pch = ' ';
			plr = false;
			pad = 0;
			fpad = -1;
			lenmod = LENMOD_NONE;
			uc = false;

			if (p > p0)
				err |= vph(p0, p - p0, arg);

			fm = true;
			continue;
		}

		fm = false;
		base = 10;

		switch (*p) {

		case '-':
			plr = true;
			fm  = true;
			break;

		case '.':
			fpad = pad;
			pad = 0;
			fm = true;
			break;

		case '%':
			ch = '%';

			err |= vph(&ch, 1, arg);
			break;

		case 'b':
			str = va_arg(ap, const char *);
			len = va_arg(ap, size_t);

			err |= write_padded(str, str ? len : 0, pad, ' ',
					    plr, NULL, vph, arg);
			break;

		case 'c':
			ch = va_arg(ap, int);

			err |= write_padded(&ch, 1, pad, ' ', plr, NULL,
					    vph, arg);
			break;

		case 'd':
		case 'i':
			switch (lenmod) {

			case LENMOD_SIZE:
				sn = va_arg(ap, ssize_t);
				break;

			default:
			case LENMOD_LONG_LONG:
				sn = va_arg(ap, signed long long);
				break;

			case LENMOD_LONG:
				sn = va_arg(ap, signed long);
				break;

			case LENMOD_NONE:
				sn = va_arg(ap, signed);
				break;
			}

			len = local_itoa(num, (sn < 0) ? -sn : sn, base,
					 false);

			err |= write_padded(num, len, pad,
					    plr ? ' ' : pch, plr,
					    (sn < 0) ? prfx_neg : NULL,
					    vph, arg);
			break;

		case 'f':
		case 'F':
			dbl = va_arg(ap, double);

			if (fpad == (size_t)-1) {
				fpad = pad;
				pad  = 0;
			}

			if (isinf(dbl)) {
				err |= write_padded("inf", 3, fpad,
						    ' ', plr, NULL, vph, arg);
			}
			else if (isnan(dbl)) {
				err |= write_padded("nan", 3, fpad,
						    ' ', plr, NULL, vph, arg);
			}
			else {
				len = local_ftoa(num, dbl,
						 pad ? min(pad, DEC_SIZE) : 6);

				err |= write_padded(num, len, fpad,
						    plr ? ' ' : pch, plr,
						    (dbl<0) ? prfx_neg : NULL,
						    vph, arg);
			}
			break;

		case 'H':
			ph     = va_arg(ap, re_printf_h *);
			ph_arg = va_arg(ap, void *);

			if (ph)
				err |= ph(&pf, ph_arg);
			break;

		case 'l':
			++lenmod;
			fm = true;
			break;

		case 'm':
			str = str_error(va_arg(ap, int), msg, sizeof(msg));
			err |= write_padded(str, str_len(str), pad,
					    ' ', plr, NULL, vph, arg);
			break;

		case 'p':
			ptr = va_arg(ap, void *);

			if (ptr) {
				len = local_itoa(num, (unsigned long int)ptr,
						 16, false);
				err |= write_padded(num, len, pad,
						    plr ? ' ' : pch, plr,
						    prfx_hex, vph, arg);
			}
			else {
				err |= write_padded(str_nil,
						    sizeof(str_nil) - 1,
						    pad, ' ', plr, NULL,
						    vph, arg);
			}
			break;

		case 'r':
			pl = va_arg(ap, const struct pl *);

			err |= write_padded(pl ? pl->p : NULL,
					    (pl && pl->p) ? pl->l : 0,
					    pad, ' ', plr, NULL, vph, arg);
			break;

		case 's':
			str = va_arg(ap, const char *);
			err |= write_padded(str, str_len(str), pad,
					    ' ', plr, NULL, vph, arg);
			break;

		case 'X':
			uc = true;
			/*@fallthrough@*/
		case 'x':
			base = 16;
			/*@fallthrough@*/
		case 'u':
			switch (lenmod) {

			case LENMOD_SIZE:
				n = va_arg(ap, size_t);
				break;

			default:
			case LENMOD_LONG_LONG:
				n = va_arg(ap, unsigned long long);
				break;

			case LENMOD_LONG:
				n = va_arg(ap, unsigned long);
				break;

			case LENMOD_NONE:
				n = va_arg(ap, unsigned);
				break;
			}

			len = local_itoa(num, n, base, uc);

			err |= write_padded(num, len, pad,
					    plr ? ' ' : pch, plr, NULL,
					    vph, arg);
			break;

		case 'v':
			str = va_arg(ap, char *);
			apl = va_arg(ap, va_list *);

			if (!str || !apl)
				break;

			err |= re_vhprintf(str, *apl, vph, arg);
			break;

		case 'W':
			uc = true;
			/*@fallthrough@*/
		case 'w':
			bptr = va_arg(ap, uint8_t *);
			len = va_arg(ap, size_t);

			len = bptr ? len : 0;
			pch = plr ? ' ' : pch;

			while (!plr && pad-- > (len * 2))
				err |= vph(&pch, 1, arg);

			for (i=0; i<len; i++) {
				const uint8_t v = *bptr++;
				uint32_t l = local_itoa(num, v, 16, uc);
				err |= write_padded(num, l, 2, '0',
						    false, NULL, vph, arg);
			}

			while (plr && pad-- > (len * 2))
				err |= vph(&pch, 1, arg);

			break;

		case 'z':
			lenmod = LENMOD_SIZE;
			fm = true;
			break;

		case 'j':
			sa = va_arg(ap, struct sa *);
			if (!sa)
				break;
			if (sa_ntop(sa, addr, sizeof(addr))) {
				err |= write_padded("?", 1, pad, ' ',
						    plr, NULL, vph, arg);
				break;
			}
			err |= write_padded(addr, strlen(addr), pad, ' ',
					    plr, NULL, vph, arg);
			break;


		case 'J':
			sa = va_arg(ap, struct sa *);
			if (!sa)
				break;
			if (sa_ntop(sa, addr, sizeof(addr))) {
				err |= write_padded("?", 1, pad, ' ',
						    plr, NULL, vph, arg);
				break;
			}

#ifdef HAVE_INET6
			if (AF_INET6 == sa_af(sa)) {
				ch = '[';
				err |= vph(&ch, 1, arg);
			}
#endif
			err |= write_padded(addr, strlen(addr), pad, ' ',
					    plr, NULL, vph, arg);
#ifdef HAVE_INET6
			if (AF_INET6 == sa_af(sa)) {
				ch = ']';
				err |= vph(&ch, 1, arg);
			}
#endif

			ch = ':';
			err |= vph(&ch, 1, arg);
			len = local_itoa(num, sa_port(sa), 10, false);
			err |= write_padded(num, len, pad,
					    plr ? ' ' : pch, plr, NULL,
					    vph, arg);

			break;

		default:
			if (('0' <= *p) && (*p <= '9')) {
				if (!pad && ('0' == *p)) {
					pch = '0';
				}
				else {
					pad *= 10;
					pad += *p - '0';
				}
				fm = true;
				break;
			}

			ch = '?';

			err |= vph(&ch, 1, arg);
			break;
		}

		if (!fm)
			p0 = p + 1;
	}

	if (!fm && p > p0)
		err |= vph(p0, p - p0, arg);

	return err;
}