}
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;
_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)
* 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);
/**
EXTRA_DIST += $(TESTS:.test=.expected)
EXTRA_DIST += test-defs.sh
EXTRA_DIST += valid.json
+EXTRA_DIST += valid_nested.json
# Note: handled by test1.test
#include <stddef.h>
#include <string.h>
#include <fcntl.h>
+#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#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);
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();
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)
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
+ {
+ fprintf(stderr,
+ "FAIL: unable to parse contents of %s: %s\n",
+ filename, json_util_get_last_err());
+ }
+ 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
"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);
}
-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
--- /dev/null
+{"foo":123, "obj2": { "obj3": { "obj4": { "foo": 999 } } } }