Implement strbuffer
authorPetri Lehtinen <petri@digip.org>
Thu, 11 Jun 2009 05:56:11 +0000 (08:56 +0300)
committerPetri Lehtinen <petri@digip.org>
Thu, 11 Jun 2009 05:56:11 +0000 (08:56 +0300)
String buffer (strbuffer) is an object that resizes automatically when
data is added to it. It was implemented by generalizing the technique
used in json_dumps().

src/Makefile.am
src/dump.c
src/strbuffer.c [new file with mode: 0644]
src/strbuffer.h [new file with mode: 0644]

index b75a60d..f477766 100644 (file)
@@ -6,6 +6,8 @@ libjansson_la_SOURCES = \
        hashtable.c \
        hashtable.h \
        load.c \
+       strbuffer.c \
+       strbuffer.h \
        util.h \
        value.c
 libjansson_la_LDFLAGS = -version-info 0:0:0
index a849b50..83f3812 100644 (file)
@@ -5,6 +5,7 @@
 #include <unistd.h>
 
 #include <jansson.h>
+#include "strbuffer.h"
 
 typedef int (*dump_func)(const char *buffer, int size, void *data);
 
@@ -15,28 +16,9 @@ struct string
     int size;
 };
 
-static int dump_to_string(const char *buffer, int size, void *data)
+static int dump_to_strbuffer(const char *buffer, int size, void *data)
 {
-    struct string *string = (struct string *)data;
-    if(string->length + size > string->size)
-    {
-        if(string->length == 0)
-            string->size = 16;
-        else
-            string->size *= 2;
-
-        string->buffer = realloc(string->buffer, string->size);
-        if(!string->buffer)
-            return -1;
-
-        memset(string->buffer + string->length, 0,
-               string->size - string->length);
-    }
-
-    memcpy(string->buffer + string->length, buffer, size);
-    string->length += size;
-
-    return 0;
+    return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
 }
 
 static int dump_to_file(const char *buffer, int size, void *data)
@@ -229,19 +211,19 @@ int json_dump(const json_t *json, const char *path, uint32_t flags)
 
 char *json_dumps(const json_t *json, uint32_t flags)
 {
-    struct string string;
+    strbuffer_t strbuff;
     char *result;
-    memset(&string, 0, sizeof(struct string));
 
-    if(do_dump(json, flags, 0, dump_to_string, (void *)&string))
+    strbuffer_init(&strbuff);
+
+    if(do_dump(json, flags, 0, dump_to_strbuffer, (void *)&strbuff))
         return NULL;
 
-    if(dump_to_string("\n", 1, (void *)&string))
+    if(dump_to_strbuffer("\n", 1, (void *)&strbuff))
         return NULL;
 
-    /* consume just the right amount of memory */
-    result = strdup(string.buffer);
-    free(string.buffer);
+    result = strbuffer_value(&strbuff);
+    strbuffer_close(&strbuff);
 
     return result;
 }
diff --git a/src/strbuffer.c b/src/strbuffer.c
new file mode 100644 (file)
index 0000000..ea74b6d
--- /dev/null
@@ -0,0 +1,62 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+#include "strbuffer.h"
+#include "util.h"
+
+#define STRBUFFER_MIN_SIZE  16
+#define STRBUFFER_FACTOR    2
+
+void strbuffer_init(strbuffer_t *strbuff)
+{
+    strbuff->value = NULL;
+    strbuff->length = 0;
+    strbuff->size = 0;
+}
+
+void strbuffer_close(strbuffer_t *strbuff)
+{
+    free(strbuff->value);
+    strbuffer_init(strbuff);
+}
+
+char *strbuffer_value(strbuffer_t *strbuff)
+{
+    return strdup(strbuff->value);
+}
+
+char *strbuffer_steal_value(strbuffer_t *strbuff)
+{
+    char *result = strbuff->value;
+    strbuffer_init(strbuff);
+    return result;
+}
+
+int strbuffer_append(strbuffer_t *strbuff, const char *string)
+{
+    return strbuffer_append_bytes(strbuff, string, strlen(string));
+}
+
+int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, int size)
+{
+    if(strbuff->length + size > strbuff->size)
+    {
+        if(strbuff->length == 0)
+            strbuff->size = STRBUFFER_MIN_SIZE;
+        else
+            strbuff->size = max(strbuff->size * STRBUFFER_FACTOR,
+                                strbuff->length + size + 1);
+
+        strbuff->value = realloc(strbuff->value, strbuff->size);
+        if(!strbuff->value)
+            return -1;
+
+        memset(strbuff->value + strbuff->length + size, 0,
+               strbuff->size - strbuff->length - size);
+    }
+
+    memcpy(strbuff->value + strbuff->length, data, size);
+    strbuff->length += size;
+
+    return 0;
+}
diff --git a/src/strbuffer.h b/src/strbuffer.h
new file mode 100644 (file)
index 0000000..2b39135
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef STRBUFFER_H
+#define STRBUFFER_H
+
+typedef struct {
+    char *value;
+    int length;
+    int size;
+} strbuffer_t;
+
+void strbuffer_init(strbuffer_t *strbuff);
+void strbuffer_close(strbuffer_t *strbuff);
+
+char *strbuffer_value(strbuffer_t *strbuff);
+char *strbuffer_steal_value(strbuffer_t *strbuff);
+
+int strbuffer_append(strbuffer_t *strbuff, const char *string);
+int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, int size);
+
+#endif