Merge branch 'issue-29'

Fixes GH-29.
This commit is contained in:
Petri Lehtinen
2011-06-30 21:48:09 +03:00
9 changed files with 137 additions and 13 deletions

View File

@@ -765,6 +765,26 @@ is in UTF-8.
*path* already exists, it is overwritten. *flags* is described
above. Returns 0 on success and -1 on error.
.. type:: json_dump_callback_t
A typedef for a function that's called by
:func:`json_dump_callback()`::
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
*buffer* points to a buffer containing a chunk of output, *size* is
the length of the buffer, and *data* is the corresponding
:func:`json_dump_callback()` argument passed through.
On error, the function should return -1 to stop the encoding
process. On success, it should return 0.
.. function:: int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags)
Call *callback* repeatedly, passing a chunk of the JSON
representation of *root* each time. *flags* is described above.
Returns 0 on success and -1 on error.
.. _apiref-decoding:

View File

@@ -19,8 +19,6 @@
#define MAX_INTEGER_STR_LENGTH 100
#define MAX_REAL_STR_LENGTH 100
typedef int (*dump_func)(const char *buffer, int size, void *data);
struct string
{
char *buffer;
@@ -28,12 +26,12 @@ struct string
int size;
};
static int dump_to_strbuffer(const char *buffer, int size, void *data)
static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
{
return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
}
static int dump_to_file(const char *buffer, int size, void *data)
static int dump_to_file(const char *buffer, size_t size, void *data)
{
FILE *dest = (FILE *)data;
if(fwrite(buffer, size, 1, dest) != 1)
@@ -44,7 +42,7 @@ static int dump_to_file(const char *buffer, int size, void *data)
/* 32 spaces (the maximum indentation size) */
static char whitespace[] = " ";
static int dump_indent(size_t flags, int depth, int space, dump_func dump, void *data)
static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data)
{
if(JSON_INDENT(flags) > 0)
{
@@ -66,7 +64,7 @@ static int dump_indent(size_t flags, int depth, int space, dump_func dump, void
return 0;
}
static int dump_string(const char *str, int ascii, dump_func dump, void *data)
static int dump_string(const char *str, int ascii, json_dump_callback_t dump, void *data)
{
const char *pos, *end;
int32_t codepoint;
@@ -166,7 +164,7 @@ static int object_key_compare_serials(const void *key1, const void *key2)
}
static int do_dump(const json_t *json, size_t flags, int depth,
dump_func dump, void *data)
json_dump_callback_t dump, void *data)
{
int ascii = flags & JSON_ENSURE_ASCII ? 1 : 0;
@@ -463,3 +461,13 @@ int json_dump_file(const json_t *json, const char *path, size_t flags)
fclose(output);
return result;
}
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags)
{
if(!(flags & JSON_ENCODE_ANY)) {
if(!json_is_array(json) && !json_is_object(json))
return -1;
}
return do_dump(json, flags, 0, callback, data);
}

View File

@@ -234,10 +234,12 @@ json_t *json_load_file(const char *path, size_t flags, json_error_t *error);
#define JSON_PRESERVE_ORDER 0x100
#define JSON_ENCODE_ANY 0x200
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
char *json_dumps(const json_t *json, size_t flags);
int json_dumpf(const json_t *json, FILE *output, size_t flags);
int json_dump_file(const json_t *json, const char *path, size_t flags);
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags);
/* custom memory allocation */

View File

@@ -13,6 +13,7 @@
#define STRBUFFER_MIN_SIZE 16
#define STRBUFFER_FACTOR 2
#define STRBUFFER_SIZE_MAX ((size_t)-1)
int strbuffer_init(strbuffer_t *strbuff)
{
@@ -64,13 +65,19 @@ int strbuffer_append_byte(strbuffer_t *strbuff, char byte)
return strbuffer_append_bytes(strbuff, &byte, 1);
}
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, int size)
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size)
{
if(strbuff->length + size >= strbuff->size)
if(size >= strbuff->size - strbuff->length)
{
size_t new_size;
char *new_value;
/* avoid integer overflow */
if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR
|| size > STRBUFFER_SIZE_MAX - 1
|| strbuff->length > STRBUFFER_SIZE_MAX - 1 - size)
return -1;
new_size = max(strbuff->size * STRBUFFER_FACTOR,
strbuff->length + size + 1);

View File

@@ -10,8 +10,8 @@
typedef struct {
char *value;
int length; /* bytes used */
int size; /* bytes allocated */
size_t length; /* bytes used */
size_t size; /* bytes allocated */
} strbuffer_t;
int strbuffer_init(strbuffer_t *strbuff);
@@ -24,7 +24,7 @@ char *strbuffer_steal_value(strbuffer_t *strbuff);
int strbuffer_append(strbuffer_t *strbuff, const char *string);
int strbuffer_append_byte(strbuffer_t *strbuff, char byte);
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, int size);
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size);
char strbuffer_pop(strbuffer_t *strbuff);

1
test/.gitignore vendored
View File

@@ -4,6 +4,7 @@ suites/api/test_array
suites/api/test_copy
suites/api/test_cpp
suites/api/test_dump
suites/api/test_dump_callback
suites/api/test_equal
suites/api/test_load
suites/api/test_loadb

View File

@@ -4,6 +4,7 @@ check_PROGRAMS = \
test_array \
test_copy \
test_dump \
test_dump_callback \
test_equal \
test_load \
test_loadb \
@@ -17,6 +18,7 @@ check_PROGRAMS = \
test_array_SOURCES = test_array.c util.h
test_copy_SOURCES = test_copy.c util.h
test_dump_SOURCES = test_dump.c util.h
test_dump_callback_SOURCES = test_dump_callback.c util.h
test_load_SOURCES = test_load.c util.h
test_loadb_SOURCES = test_loadb.c util.h
test_memory_funcs_SOURCES = test_memory_funcs.c util.h

View File

@@ -47,6 +47,7 @@ json_object_iter_set_new
json_dumps
json_dumpf
json_dump_file
json_dump_callback
json_loads
json_loadf
json_load_file

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
*
* Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <jansson.h>
#include <string.h>
#include <stdlib.h>
#include "util.h"
struct my_sink {
char *buf;
size_t off;
size_t cap;
};
static int my_writer(const char *buffer, size_t len, void *data) {
struct my_sink *s = data;
if (len > s->cap - s->off) {
return -1;
}
memcpy(s->buf + s->off, buffer, len);
s->off += len;
return 0;
}
int main(void)
{
struct my_sink s;
json_t *json;
const char str[] = "[\"A\", {\"B\": \"C\", \"e\": false}, 1, null, \"foo\"]";
char *dumped_to_string;
json = json_loads(str, 0, NULL);
if(!json) {
fail("json_loads failed");
}
dumped_to_string = json_dumps(json, 0);
if (!dumped_to_string) {
json_decref(json);
fail("json_dumps failed");
}
s.off = 0;
s.cap = strlen(dumped_to_string);
s.buf = malloc(s.cap);
if (!s.buf) {
json_decref(json);
free(dumped_to_string);
fail("malloc failed");
}
if (json_dump_callback(json, my_writer, &s, 0) == -1) {
json_decref(json);
free(dumped_to_string);
free(s.buf);
fail("json_dump_callback failed on an exact-length sink buffer");
}
if (strncmp(dumped_to_string, s.buf, s.off) != 0) {
json_decref(json);
free(dumped_to_string);
free(s.buf);
fail("json_dump_callback and json_dumps did not produce identical output");
}
s.off = 1;
if (json_dump_callback(json, my_writer, &s, 0) != -1) {
json_decref(json);
free(dumped_to_string);
free(s.buf);
fail("json_dump_callback succeeded on a short buffer when it should have failed");
}
json_decref(json);
free(dumped_to_string);
free(s.buf);
return EXIT_SUCCESS;
}