mirror of
https://github.com/json-c/json-c.git
synced 2026-03-13 18:19:06 +08:00
Add a json_object_from_fd_ex() function, to allow the max nesting depth to be specified.
This commit is contained in:
28
json_util.c
28
json_util.c
@@ -82,6 +82,10 @@ void _json_c_set_last_err(const char *err_fmt, ...)
|
||||
}
|
||||
|
||||
struct json_object* json_object_from_fd(int fd)
|
||||
{
|
||||
return json_object_from_fd_ex(fd, -1);
|
||||
}
|
||||
struct json_object* json_object_from_fd_ex(int fd, int in_depth)
|
||||
{
|
||||
struct printbuf *pb;
|
||||
struct json_object *obj;
|
||||
@@ -92,17 +96,35 @@ struct json_object* json_object_from_fd(int fd)
|
||||
_json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int depth = JSON_TOKENER_DEFAULT_DEPTH;
|
||||
if (in_depth != -1)
|
||||
depth = in_depth;
|
||||
json_tokener *tok = json_tokener_new_ex(depth);
|
||||
if (!tok)
|
||||
{
|
||||
_json_c_set_last_err("json_object_from_fd: unable to allocate json_tokener(depth=%d): %s\n", depth, strerror(errno));
|
||||
printbuf_free(pb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
|
||||
printbuf_memappend(pb, buf, ret);
|
||||
}
|
||||
if(ret < 0) {
|
||||
_json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno));
|
||||
json_tokener_free(tok);
|
||||
printbuf_free(pb);
|
||||
return NULL;
|
||||
}
|
||||
obj = json_tokener_parse(pb->buf);
|
||||
printbuf_free(pb);
|
||||
return obj;
|
||||
|
||||
obj = json_tokener_parse_ex(tok, pb->buf, printbuf_length(pb));
|
||||
if (obj == NULL)
|
||||
_json_c_set_last_err("json_tokener_parse_ex failed: %s\n", json_tokener_error_desc(json_tokener_get_error(tok)));
|
||||
|
||||
json_tokener_free(tok);
|
||||
printbuf_free(pb);
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct json_object* json_object_from_file(const char *filename)
|
||||
|
||||
12
json_util.h
12
json_util.h
@@ -50,8 +50,20 @@ JSON_EXPORT struct json_object* json_object_from_file(const char *filename);
|
||||
* Note, that the fd must be readable at the actual position, i.e.
|
||||
* use lseek(fd, 0, SEEK_SET) before.
|
||||
*
|
||||
* The depth argument specifies the maximum object depth to pass to
|
||||
* json_tokener_new_ex(). When depth == -1, JSON_TOKENER_DEFAULT_DEPTH
|
||||
* is used instead.
|
||||
*
|
||||
* Returns NULL on failure. See json_util_get_last_err() for details.
|
||||
*/
|
||||
JSON_EXPORT struct json_object* json_object_from_fd_ex(int fd, int depth);
|
||||
|
||||
/**
|
||||
* Create a JSON object from an already opened file descriptor, using
|
||||
* the default maximum object depth. (JSON_TOKENER_DEFAULT_DEPTH)
|
||||
*
|
||||
* See json_object_from_fd_ex() for details.
|
||||
*/
|
||||
JSON_EXPORT struct json_object* json_object_from_fd(int fd);
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,6 +36,7 @@ EXTRA_DIST += $(TESTS)
|
||||
EXTRA_DIST += $(TESTS:.test=.expected)
|
||||
EXTRA_DIST += test-defs.sh
|
||||
EXTRA_DIST += valid.json
|
||||
EXTRA_DIST += valid_nested.json
|
||||
|
||||
|
||||
# Note: handled by test1.test
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -13,6 +14,7 @@
|
||||
#include "json_util.h"
|
||||
|
||||
static void test_read_valid_with_fd(const char *testdir);
|
||||
static void test_read_valid_nested_with_fd(const char *testdir);
|
||||
static void test_read_nonexistant();
|
||||
static void test_read_closed(void);
|
||||
|
||||
@@ -129,6 +131,7 @@ int main(int argc, char **argv)
|
||||
testdir = argv[1];
|
||||
|
||||
test_read_valid_with_fd(testdir);
|
||||
test_read_valid_nested_with_fd(testdir);
|
||||
test_read_nonexistant();
|
||||
test_read_closed();
|
||||
test_write_to_file();
|
||||
@@ -137,7 +140,8 @@ int main(int argc, char **argv)
|
||||
|
||||
static void test_read_valid_with_fd(const char *testdir)
|
||||
{
|
||||
const char *filename = "./valid.json";
|
||||
char filename[PATH_MAX];
|
||||
(void)snprintf(filename, sizeof(filename), "%s/valid.json", testdir);
|
||||
|
||||
int d = open(filename, O_RDONLY, 0);
|
||||
if (d < 0)
|
||||
@@ -150,8 +154,8 @@ static void test_read_valid_with_fd(const char *testdir)
|
||||
json_object *jso = json_object_from_fd(d);
|
||||
if (jso != NULL)
|
||||
{
|
||||
printf("OK: json_object_from_fd(%s)=%s\n",
|
||||
filename, json_object_to_json_string(jso));
|
||||
printf("OK: json_object_from_fd(valid.json)=%s\n",
|
||||
json_object_to_json_string(jso));
|
||||
json_object_put(jso);
|
||||
}
|
||||
else
|
||||
@@ -163,6 +167,50 @@ static void test_read_valid_with_fd(const char *testdir)
|
||||
close(d);
|
||||
}
|
||||
|
||||
static void test_read_valid_nested_with_fd(const char *testdir)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
(void)snprintf(filename, sizeof(filename), "%s/valid_nested.json", testdir);
|
||||
|
||||
int d = open(filename, O_RDONLY, 0);
|
||||
if (d < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"FAIL: unable to open %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
json_object *jso = json_object_from_fd_ex(d, 20);
|
||||
if (jso != NULL)
|
||||
{
|
||||
printf("OK: json_object_from_fd_ex(valid_nested.json, 20)=%s\n",
|
||||
json_object_to_json_string(jso));
|
||||
json_object_put(jso);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"FAIL: unable to parse contents of %s: %s\n",
|
||||
filename, json_util_get_last_err());
|
||||
}
|
||||
|
||||
(void)lseek(d, SEEK_SET, 0);
|
||||
|
||||
jso = json_object_from_fd_ex(d, 3);
|
||||
if (jso != NULL)
|
||||
{
|
||||
printf("FAIL: json_object_from_fd_ex(%s, 3)=%s\n",
|
||||
filename, json_object_to_json_string(jso));
|
||||
json_object_put(jso);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("OK: correctly unable to parse contents of valid_nested.json with low max depth: %s\n",
|
||||
json_util_get_last_err());
|
||||
}
|
||||
close(d);
|
||||
}
|
||||
|
||||
static void test_read_nonexistant()
|
||||
{
|
||||
const char *filename = "./not_present.json";
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
OK: json_object_from_fd(./valid.json)={ "foo": 123 }
|
||||
OK: json_object_from_fd(valid.json)={ "foo": 123 }
|
||||
OK: json_object_from_fd_ex(valid_nested.json, 20)={ "foo": 123, "obj2": { "obj3": { "obj4": { "foo": 999 } } } }
|
||||
OK: correctly unable to parse contents of valid_nested.json with low max depth: json_tokener_parse_ex failed: nesting too deep
|
||||
|
||||
OK: json_object_from_file(./not_present.json) correctly returned NULL: json_object_from_file: error opening file ./not_present.json: ERRNO=ENOENT
|
||||
|
||||
OK: json_object_from_fd(closed_fd), expecting NULL, EBADF, got:NULL, json_object_from_fd: error reading fd 10: ERRNO=EBADF
|
||||
|
||||
1
tests/valid_nested.json
Normal file
1
tests/valid_nested.json
Normal file
@@ -0,0 +1 @@
|
||||
{"foo":123, "obj2": { "obj3": { "obj4": { "foo": 999 } } } }
|
||||
Reference in New Issue
Block a user