From: Petri Lehtinen Date: Thu, 11 Jun 2009 05:56:11 +0000 (+0300) Subject: Implement strbuffer X-Git-Tag: v1.0~47 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=jansson.git;a=commitdiff_plain;h=197d3aa1608a3442d95152d20e15c2b32204aaaf Implement strbuffer 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(). --- diff --git a/src/Makefile.am b/src/Makefile.am index b75a60d..f477766 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/dump.c b/src/dump.c index a849b50..83f3812 100644 --- a/src/dump.c +++ b/src/dump.c @@ -5,6 +5,7 @@ #include #include +#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 index 0000000..ea74b6d --- /dev/null +++ b/src/strbuffer.c @@ -0,0 +1,62 @@ +#define _GNU_SOURCE +#include +#include +#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 index 0000000..2b39135 --- /dev/null +++ b/src/strbuffer.h @@ -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