commit
cbb80baf03
@ -232,10 +232,13 @@ json_t *json_deep_copy(json_t *value);
|
|||||||
#define JSON_DISABLE_EOF_CHECK 0x2
|
#define JSON_DISABLE_EOF_CHECK 0x2
|
||||||
#define JSON_DECODE_ANY 0x4
|
#define JSON_DECODE_ANY 0x4
|
||||||
|
|
||||||
|
typedef int (*json_load_callback_t)(void *buffer, size_t buflen, void *arg);
|
||||||
|
|
||||||
json_t *json_loads(const char *input, size_t flags, json_error_t *error);
|
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_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_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_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);
|
||||||
|
|
||||||
|
|
||||||
/* encoding */
|
/* encoding */
|
||||||
|
55
src/load.c
55
src/load.c
@ -990,3 +990,58 @@ json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_BUF_LEN 1024
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char data[MAX_BUF_LEN];
|
||||||
|
size_t len;
|
||||||
|
size_t pos;
|
||||||
|
json_load_callback_t callback;
|
||||||
|
void *arg;
|
||||||
|
} callback_data_t;
|
||||||
|
|
||||||
|
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)
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = stream->data[stream->pos];
|
||||||
|
stream->pos++;
|
||||||
|
return (unsigned char)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags, json_error_t *error)
|
||||||
|
{
|
||||||
|
lex_t lex;
|
||||||
|
json_t *result;
|
||||||
|
|
||||||
|
callback_data_t stream_data;
|
||||||
|
|
||||||
|
memset(&stream_data, 0, sizeof(stream_data));
|
||||||
|
stream_data.callback = callback;
|
||||||
|
stream_data.arg = arg;
|
||||||
|
|
||||||
|
jsonp_error_init(error, "<callback>");
|
||||||
|
|
||||||
|
if (callback == NULL) {
|
||||||
|
error_set(error, NULL, "wrong arguments");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lex_init(&lex, (get_func)callback_get, &stream_data))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
result = parse_json(&lex, flags, error);
|
||||||
|
|
||||||
|
lex_close(&lex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ check_PROGRAMS = \
|
|||||||
test_equal \
|
test_equal \
|
||||||
test_load \
|
test_load \
|
||||||
test_loadb \
|
test_loadb \
|
||||||
|
test_load_callback \
|
||||||
test_memory_funcs \
|
test_memory_funcs \
|
||||||
test_number \
|
test_number \
|
||||||
test_object \
|
test_object \
|
||||||
|
75
test/suites/api/test_load_callback.c
Normal file
75
test/suites/api/test_load_callback.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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_source {
|
||||||
|
const char *buf;
|
||||||
|
size_t off;
|
||||||
|
size_t cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char my_str[] = "[\"A\", {\"B\": \"C\", \"e\": false}, 1, null, \"foo\"]";
|
||||||
|
|
||||||
|
static int greedy_reader(void *buf, size_t buflen, void *arg)
|
||||||
|
{
|
||||||
|
struct my_source *s = arg;
|
||||||
|
if (buflen > s->cap - s->off)
|
||||||
|
buflen = s->cap - s->off;
|
||||||
|
if (buflen > 0) {
|
||||||
|
memcpy(buf, s->buf + s->off, buflen);
|
||||||
|
s->off += buflen;
|
||||||
|
return buflen;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_tests()
|
||||||
|
{
|
||||||
|
struct my_source s;
|
||||||
|
json_t *json;
|
||||||
|
json_error_t error;
|
||||||
|
|
||||||
|
s.off = 0;
|
||||||
|
s.cap = strlen(my_str);
|
||||||
|
s.buf = my_str;
|
||||||
|
|
||||||
|
json = json_load_callback(greedy_reader, &s, 0, &error);
|
||||||
|
|
||||||
|
if (!json)
|
||||||
|
fail("json_load_callback failed on a valid callback");
|
||||||
|
json_decref(json);
|
||||||
|
|
||||||
|
s.off = 0;
|
||||||
|
s.cap = strlen(my_str) - 1;
|
||||||
|
s.buf = my_str;
|
||||||
|
|
||||||
|
json = json_load_callback(greedy_reader, &s, 0, &error);
|
||||||
|
if (json) {
|
||||||
|
json_decref(json);
|
||||||
|
fail("json_load_callback should have failed on an incomplete stream, but it didn't");
|
||||||
|
}
|
||||||
|
if (strcmp(error.source, "<callback>") != 0) {
|
||||||
|
fail("json_load_callback returned an invalid error source");
|
||||||
|
}
|
||||||
|
if (strcmp(error.text, "']' expected near end of file") != 0) {
|
||||||
|
fail("json_load_callback returned an invalid error message for an unclosed top-level array");
|
||||||
|
}
|
||||||
|
|
||||||
|
json = json_load_callback(NULL, NULL, 0, &error);
|
||||||
|
if (json) {
|
||||||
|
json_decref(json);
|
||||||
|
fail("json_load_callback should have failed on NULL load callback, but it didn't");
|
||||||
|
}
|
||||||
|
if (strcmp(error.text, "wrong arguments") != 0) {
|
||||||
|
fail("json_load_callback returned an invalid error message for a NULL load callback");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user