#include <config.h>
#include <stdarg.h>
-#include "c-ctype.h"
#include "virbuffer.h"
#include "virerror.h"
static void
virBufferSetError(virBufferPtr buf, int error)
{
- VIR_FREE(buf->content);
- buf->size = 0;
- buf->use = 0;
- buf->indent = 0;
+ virBufferFreeAndReset(buf);
buf->error = error;
}
size_t
virBufferGetEffectiveIndent(const virBuffer *buf)
{
- if (buf->use && buf->content[buf->use - 1] != '\n')
+ if (buf->str && buf->str->len && buf->str->str[buf->str->len - 1] != '\n')
return 0;
return buf->indent;
/**
- * virBufferGrow:
+ * virBufferInitialize
* @buf: the buffer
- * @len: the minimum free size to allocate on top of existing used space
*
- * Grow the available space of a buffer to at least @len bytes.
- *
- * Returns zero on success or -1 on error
+ * Ensures that the internal GString container is allocated.
*/
-static int
-virBufferGrow(virBufferPtr buf, unsigned int len)
+static void
+virBufferInitialize(virBufferPtr buf)
{
- int size;
+ if (!buf->str)
+ buf->str = g_string_new(NULL);
+}
- if (buf->error)
- return -1;
- if ((len + buf->use) < buf->size)
- return 0;
+static void
+virBufferApplyIndent(virBufferPtr buf)
+{
+ const char space[] = " ";
+ size_t spacesz = sizeof(space) - 1;
+ size_t toindent = virBufferGetEffectiveIndent(buf);
- size = buf->use + len + 1000;
+ if (toindent == 0)
+ return;
- if (VIR_REALLOC_N_QUIET(buf->content, size) < 0) {
- virBufferSetError(buf, errno);
- return -1;
+ while (toindent > spacesz) {
+ g_string_append_len(buf->str, space, spacesz);
+ toindent -= spacesz;
}
- buf->size = size;
- return 0;
+
+ g_string_append_len(buf->str, space, toindent);
}
+
/**
* virBufferAdd:
* @buf: the buffer to append to
void
virBufferAdd(virBufferPtr buf, const char *str, int len)
{
- unsigned int needSize;
- size_t indent;
-
if (!str || !buf || buf->error || (len == 0 && buf->indent == 0))
return;
- indent = virBufferGetEffectiveIndent(buf);
+ virBufferInitialize(buf);
+ virBufferApplyIndent(buf);
if (len < 0)
- len = strlen(str);
-
- needSize = buf->use + indent + len + 2;
- if (virBufferGrow(buf, needSize - buf->use) < 0)
- return;
-
- memset(&buf->content[buf->use], ' ', indent);
- memcpy(&buf->content[buf->use + indent], str, len);
- buf->use += indent + len;
- buf->content[buf->use] = '\0';
+ g_string_append(buf->str, str);
+ else
+ g_string_append_len(buf->str, str, len);
}
/**
void
virBufferAddBuffer(virBufferPtr buf, virBufferPtr toadd)
{
- if (!toadd)
+ if (!toadd || !toadd->str)
return;
if (!buf)
goto cleanup;
}
- if (virBufferGrow(buf, toadd->use) < 0)
- goto cleanup;
-
- memcpy(&buf->content[buf->use], toadd->content, toadd->use);
- buf->use += toadd->use;
- buf->content[buf->use] = '\0';
+ virBufferInitialize(buf);
+ g_string_append_len(buf->str, toadd->str->str, toadd->str->len);
cleanup:
virBufferFreeAndReset(toadd);
{
if (!buf || buf->error)
return NULL;
- return buf->use ? buf->content : "";
+
+ if (!buf->str ||
+ buf->str->len == 0)
+ return "";
+
+ return buf->str->str;
}
/**
char *
virBufferContentAndReset(virBufferPtr buf)
{
- char *str;
- if (buf == NULL)
- return NULL;
+ char *str = NULL;
- if (buf->error) {
- memset(buf, 0, sizeof(*buf));
+ if (!buf)
return NULL;
- }
- str = buf->content;
+ if (buf->str)
+ str = g_string_free(buf->str, false);
+
memset(buf, 0, sizeof(*buf));
return str;
}
*/
void virBufferFreeAndReset(virBufferPtr buf)
{
- if (buf)
- virBufferSetError(buf, 0);
+ if (!buf)
+ return;
+
+ if (buf->str)
+ g_string_free(buf->str, true);
+
+ memset(buf, 0, sizeof(*buf));
}
/**
size_t
virBufferUse(const virBuffer *buf)
{
- if (buf == NULL)
+ if (!buf || !buf->str)
return 0;
- return buf->use;
+ return buf->str->len;
}
/**
void
virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr)
{
- int size, count, grow_size;
- va_list copy;
-
if ((format == NULL) || (buf == NULL))
return;
if (buf->error)
return;
- virBufferAddLit(buf, ""); /* auto-indent */
+ virBufferInitialize(buf);
+ virBufferApplyIndent(buf);
- if (buf->size == 0 &&
- virBufferGrow(buf, 100) < 0)
- return;
-
- va_copy(copy, argptr);
-
- size = buf->size - buf->use;
- if ((count = vsnprintf(&buf->content[buf->use],
- size, format, copy)) < 0) {
- virBufferSetError(buf, errno);
- va_end(copy);
- return;
- }
- va_end(copy);
-
- /* Grow buffer if necessary and retry */
- if (count >= size) {
- buf->content[buf->use] = 0;
-
- grow_size = (count + 1 > 1000) ? count + 1 : 1000;
- if (virBufferGrow(buf, grow_size) < 0)
- return;
-
- size = buf->size - buf->use;
- if ((count = vsnprintf(&buf->content[buf->use],
- size, format, argptr)) < 0) {
- virBufferSetError(buf, errno);
- return;
- }
- }
- buf->use += count;
+ g_string_append_vprintf(buf->str, format, argptr);
}
}
-static bool
-virBufferURIEncodeCharIsUnencoded(char c)
-{
- if (c == '-' || c == '.' || c == '_' || c == '~')
- return true;
-
- return c_isalnum(c);
-}
-
-
/**
* virBufferURIEncodeString:
* @buf: the buffer to append to
void
virBufferURIEncodeString(virBufferPtr buf, const char *str)
{
- int grow_size = 0;
- const char *p;
- unsigned char uc;
- const char *hex = "0123456789ABCDEF";
-
if ((buf == NULL) || (str == NULL))
return;
if (buf->error)
return;
- virBufferAddLit(buf, ""); /* auto-indent */
-
- for (p = str; *p; ++p) {
- if (virBufferURIEncodeCharIsUnencoded(*p))
- grow_size++;
- else
- grow_size += 3; /* %ab */
- }
-
- if (virBufferGrow(buf, grow_size) < 0)
- return;
-
- for (p = str; *p; ++p) {
- if (virBufferURIEncodeCharIsUnencoded(*p)) {
- buf->content[buf->use++] = *p;
- } else {
- uc = (unsigned char) *p;
- buf->content[buf->use++] = '%';
- buf->content[buf->use++] = hex[uc >> 4];
- buf->content[buf->use++] = hex[uc & 0xf];
- }
- }
+ virBufferInitialize(buf);
+ virBufferApplyIndent(buf);
- buf->content[buf->use] = '\0';
+ g_string_append_uri_escaped(buf->str, str, NULL, false);
}
/**
{
size_t len2 = 0;
- if (!buf || buf->error)
+ if (!buf || buf->error || !buf->str)
return;
+
if (!str && len < 0)
return;
- if (len > 0 && len > buf->use)
+
+ if (len > 0 && len > buf->str->len)
return;
+
if (str) {
len2 = strlen(str);
- if (len2 > buf->use ||
- memcmp(&buf->content[buf->use - len2], str, len2) != 0)
+ if (len2 > buf->str->len ||
+ memcmp(&buf->str->str[buf->str->len - len2], str, len2) != 0)
return;
}
- buf->use -= len < 0 ? len2 : len;
- buf->content[buf->use] = '\0';
+
+ if (len < 0)
+ len = len2;
+
+ g_string_truncate(buf->str, buf->str->len - len);
}