diff --git a/doc/apiref.rst b/doc/apiref.rst index 1c3a85b..0128cc0 100644 --- a/doc/apiref.rst +++ b/doc/apiref.rst @@ -967,6 +967,34 @@ The following functions perform the actual JSON decoding. filled with information about the error. *flags* is described above. +.. type:: json_load_callback_t + + A typedef for a function that's called by + :func:`json_load_callback()` to read a chunk of input data:: + + typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); + + *buffer* points to a buffer of *buflen* bytes, and *data* is the + corresponding :func:`json_load_callback()` argument passed through. + + On error, the function should return ``(size_t)-1`` to abort the + decoding process. When there's no data left, it should return 0 to + report that the end of input has been reached. + + .. versionadded:: 2.4 + +.. function:: json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error) + + .. refcounting:: new + + Decodes the JSON text produced by repeated calls to *callback*, and + returns the array or object it contains, or *NULL* on error, in + which case *error* is filled with information about the error. + *data* is passed through to *callback* on each call. *flags* is + described above. + + .. versionadded:: 2.4 + .. _apiref-pack: diff --git a/src/jansson.h b/src/jansson.h index 8910e3d..e22b68f 100644 --- a/src/jansson.h +++ b/src/jansson.h @@ -232,13 +232,13 @@ json_t *json_deep_copy(json_t *value); #define JSON_DISABLE_EOF_CHECK 0x2 #define JSON_DECODE_ANY 0x4 -typedef int (*json_load_callback_t)(void *buffer, size_t buflen, void *arg); +typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); json_t *json_loads(const char *input, size_t flags, json_error_t *error); json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error); json_t *json_loadf(FILE *input, size_t flags, json_error_t *error); json_t *json_load_file(const char *path, size_t flags, json_error_t *error); -json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags, json_error_t *error); +json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error); /* encoding */ diff --git a/src/load.c b/src/load.c index 32d7901..e245476 100644 --- a/src/load.c +++ b/src/load.c @@ -1006,11 +1006,11 @@ static int callback_get(void *data) { char c; callback_data_t *stream = data; - + if(stream->pos >= stream->len) { stream->pos = 0; stream->len = stream->callback(stream->data, MAX_BUF_LEN, stream->arg); - if (stream->len <=0) + if(stream->len == 0 || stream->len == (size_t)-1) return EOF; } diff --git a/test/suites/api/test_load_callback.c b/test/suites/api/test_load_callback.c index 33304dd..9449528 100644 --- a/test/suites/api/test_load_callback.c +++ b/test/suites/api/test_load_callback.c @@ -18,7 +18,7 @@ struct my_source { static const char my_str[] = "[\"A\", {\"B\": \"C\", \"e\": false}, 1, null, \"foo\"]"; -static int greedy_reader(void *buf, size_t buflen, void *arg) +static size_t greedy_reader(void *buf, size_t buflen, void *arg) { struct my_source *s = arg; if (buflen > s->cap - s->off)