Пример #1
0
/*
 * Format the given argument list and append the resulting string to an vsb.
 */
int
VSB_vprintf(struct vsb *s, const char *fmt, va_list ap)
{
	va_list ap_copy;
	int len;

	assert_VSB_integrity(s);
	assert_VSB_state(s, 0);

	KASSERT(fmt != NULL,
	    ("%s called with a NULL format string", __func__));

	if (s->s_error != 0)
		return (-1);
	_vsb_indent(s);

	/*
	 * For the moment, there is no way to get vsnprintf(3) to hand
	 * back a character at a time, to push everything into
	 * VSB_putc_func() as was done for the kernel.
	 *
	 * In userspace, while drains are useful, there's generally
	 * not a problem attempting to malloc(3) on out of space.  So
	 * expand a userland vsb if there is not enough room for the
	 * data produced by VSB_[v]printf(3).
	 */

	do {
		va_copy(ap_copy, ap);
		len = vsnprintf(&s->s_buf[s->s_len], VSB_FREESPACE(s) + 1,
		    fmt, ap_copy);
		va_end(ap_copy);
	} while (len > VSB_FREESPACE(s) &&
	    VSB_extend(s, len - VSB_FREESPACE(s)) == 0);

	/*
	 * s->s_len is the length of the string, without the terminating nul.
	 * When updating s->s_len, we must subtract 1 from the length that
	 * we passed into vsnprintf() because that length includes the
	 * terminating nul.
	 *
	 * vsnprintf() returns the amount that would have been copied,
	 * given sufficient space, so don't over-increment s_len.
	 */
	if (VSB_FREESPACE(s) < len)
		len = VSB_FREESPACE(s);
	s->s_len += len;
	if (!VSB_HASROOM(s) && !VSB_CANEXTEND(s))
		s->s_error = ENOMEM;

	KASSERT(s->s_len < s->s_size,
	    ("wrote past end of vsb (%d >= %d)", s->s_len, s->s_size));

	if (s->s_error != 0)
		return (-1);
	return (0);
}
Пример #2
0
static void
_vsb_indent(struct vsb *s)
{
	if (s->s_indent == 0 || s->s_error != 0 ||
	    (s->s_len > 0 && s->s_buf[s->s_len - 1] != '\n'))
		return;
	if (VSB_FREESPACE(s) <= s->s_indent &&
	    VSB_extend(s, s->s_indent) < 0) {
		s->s_error = ENOMEM;
		return;
	}
	memset(s->s_buf + s->s_len, ' ', s->s_indent);
	s->s_len += s->s_indent;
}
Пример #3
0
Файл: vsb.c Проект: weongyo/eel
/*
 * Append a byte to an vsb.  This is the core function for appending
 * to an vsb and is the main place that deals with extending the
 * buffer and marking overflow.
 */
static void
VSB_put_byte(struct vsb *s, int c)
{

	assert_VSB_integrity(s);
	assert_VSB_state(s, 0);

	if (s->s_error != 0)
		return;
	if (VSB_FREESPACE(s) <= 0) {
		if (VSB_extend(s, 1) < 0)
			s->s_error = ENOMEM;
		if (s->s_error != 0)
			return;
	}
	s->s_buf[s->s_len++] = (char)c;
}
Пример #4
0
/*
 * Append a byte string to an vsb.
 */
int
VSB_bcat(struct vsb *s, const void *buf, ssize_t len)
{
	assert_VSB_integrity(s);
	assert_VSB_state(s, 0);

	assert(len >= 0);
	if (s->s_error != 0)
		return (-1);
	if (len == 0)
		return (0);
	_vsb_indent(s);
	if (len > VSB_FREESPACE(s)) {
		if (VSB_extend(s, len - VSB_FREESPACE(s)) < 0)
			s->s_error = ENOMEM;
		if (s->s_error != 0)
			return (-1);
	}
	memcpy(s->s_buf + s->s_len, buf, len);
	s->s_len += len;
	return (0);
}