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().
This commit is contained in:
parent
9b825f7b18
commit
197d3aa160
@ -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
|
||||
|
38
src/dump.c
38
src/dump.c
@ -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;
|
||||
}
|
||||
|
62
src/strbuffer.c
Normal file
62
src/strbuffer.c
Normal file
@ -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;
|
||||
}
|
19
src/strbuffer.h
Normal file
19
src/strbuffer.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user