summaryrefslogtreecommitdiff
path: root/extmod/modujson.c
diff options
context:
space:
mode:
Diffstat (limited to 'extmod/modujson.c')
-rw-r--r--extmod/modujson.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/extmod/modujson.c b/extmod/modujson.c
index 6b24bf578..daefe18ba 100644
--- a/extmod/modujson.c
+++ b/extmod/modujson.c
@@ -53,6 +53,10 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
+#define JSON_DEBUG(...) (void)0
+// #define JSON_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
+
+
// The function below implements a simple non-recursive JSON parser.
//
// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
@@ -80,6 +84,7 @@ typedef struct _ujson_stream_t {
STATIC byte ujson_stream_next(ujson_stream_t *s) {
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
+ JSON_DEBUG(" usjon_stream_next err:%2d cur: %c \n", s->errcode, s->cur);
if (s->errcode != 0) {
mp_raise_OSError(s->errcode);
}
@@ -92,6 +97,7 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ);
ujson_stream_t s = {stream_obj, stream_p->read, 0, 0};
+ JSON_DEBUG("got JSON stream\n");
vstr_t vstr;
vstr_init(&vstr, 8);
mp_obj_list_t stack; // we use a list as a simple stack for nested JSON
@@ -101,6 +107,15 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
mp_obj_type_t *stack_top_type = NULL;
mp_obj_t stack_key = MP_OBJ_NULL;
S_NEXT(s);
+ // Eat _leading_ whitespace.
+ // If we eat trailing whitespace we will block for timeout on streams like UART that
+ // wait for requested data. Furthermore, it is an OSError to read(1) and incur
+ // a timeout on those APIs.
+ // For these reasons, we must only eat _leading_ whitespace.
+ while (unichar_isspace(S_CUR(s))) {
+ JSON_DEBUG("Eating leading whitespace");
+ S_NEXT(s);
+ }
for (;;) {
cont:
if (S_END(s)) {
@@ -262,14 +277,9 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
}
}
success:
- // eat trailing whitespace
- while (unichar_isspace(S_CUR(s))) {
- S_NEXT(s);
- }
- if (!S_END(s)) {
- // unexpected chars
- goto fail;
- }
+ // It is legal for a stream to have contents before and after JSON.
+ // If this parser has consumed a full successful JSON and its parse
+ // stack is empty, the parse has succeeded.
if (stack_top == MP_OBJ_NULL || stack.len != 0) {
// not exactly 1 object
goto fail;