--- /dev/null
+/*
+ * buffer.h: Library of miscellaneous stuff for other libvsc* libraries
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*!
+ * @file
+ */
+
+#ifndef __VSC_MISC__BUFFER_H__
+#define __VSC_MISC__BUFFER_H__
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+vsc_buffer_init (struct VscBuffer *buffer);
+
+void
+vsc_buffer_append (struct VscBuffer *buffer, const char *string);
+
+void
+vsc_buffer_sprintf (struct VscBuffer *buffer, const char *format, ...);
+
+char *
+vsc_buffer_take (struct VscBuffer *buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VSC_MISC__BUFFER_H__ */
--- /dev/null
+/*
+ * buffer.c: Library of miscellaneous stuff for other libvsc* libraries
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "../include/libvscmisc/assert.h"
+#include "../include/libvscmisc/buffer.h"
+#include "../include/libvscmisc/memory.h"
+
+static int
+_grow (struct VscBuffer *buffer, size_t length)
+{
+ size_t total;
+ char *content;
+
+ VSC__ASSERT (buffer != NULL);
+
+ if (buffer->error) {
+ return -1;
+ }
+
+ if ((length + buffer->used) < buffer->allocated) {
+ return 0;
+ }
+
+ total = buffer->used + length + 512 - (length % 512);
+ content = realloc (buffer->content, total);
+
+ if (content == NULL) {
+ vsc_free (&buffer->content);
+
+ buffer->allocated = 0;
+ buffer->used = 0;
+ buffer->error = TRUE;
+
+ return -1;
+ } else {
+ buffer->content = content;
+ buffer->allocated = total;
+
+ return 0;
+ }
+}
+
+void
+vsc_buffer_init (struct VscBuffer *buffer)
+{
+ VSC__ASSERT (buffer != NULL);
+
+ buffer->content = NULL;
+ buffer->allocated = 0;
+ buffer->used = 0;
+ buffer->error = FALSE;
+}
+
+void
+vsc_buffer_append (struct VscBuffer *buffer, const char *string)
+{
+ size_t length;
+ size_t total;
+
+ VSC__ASSERT (buffer != NULL);
+ VSC__ASSERT (string != NULL);
+
+ if (buffer->error) {
+ return;
+ }
+
+ length = strlen (string);
+ total = buffer->used + length + 2;
+
+ if (total > buffer->allocated) {
+ if (_grow (buffer, total - buffer->used) < 0) {
+ return;
+ }
+ }
+
+ memcpy (&buffer->content[buffer->used], string, length);
+
+ buffer->used += length;
+ buffer->content[buffer->used] = '\0';
+}
+
+void
+vsc_buffer_sprintf (struct VscBuffer *buffer, const char *format, ...)
+{
+ size_t unused;
+ int length;
+ va_list args, tmp;
+
+ VSC__ASSERT (buffer != NULL);
+ VSC__ASSERT (format != NULL);
+
+ if (buffer->error) {
+ return;
+ }
+
+ if (buffer->allocated == 0) {
+ if (_grow (buffer, 512) < 0) {
+ return;
+ }
+ }
+
+ unused = buffer->allocated - buffer->used - 1;
+
+ va_start (args, format);
+ va_copy (tmp, args);
+
+ while ((length = vsnprintf (&buffer->content[buffer->used], unused,
+ format, tmp)) < 0 ||
+ (size_t) length >= unused - 1) {
+ buffer->content[buffer->used] = '\0';
+
+ va_end (tmp);
+
+ if (_grow (buffer, length) < 0) {
+ return;
+ }
+
+ unused = buffer->allocated - buffer->used - 1;
+
+ va_copy (tmp, args);
+ }
+
+ va_end (tmp);
+
+ buffer->used += length;
+ buffer->content[buffer->used] = '\0';
+}
+
+char *
+vsc_buffer_take (struct VscBuffer *buffer)
+{
+ char *content = NULL;
+
+ if (buffer->error) {
+ return NULL;
+ }
+
+ content = buffer->content;
+
+ memset (buffer, 0, sizeof (struct VscBuffer));
+
+ return content;
+}