diff options
| author | Daniel Pollard <daniel@learnweaver.com> | 2020-05-12 14:41:28 +1000 |
|---|---|---|
| committer | Daniel Pollard <daniel@learnweaver.com> | 2020-05-12 14:41:28 +1000 |
| commit | ee2cb703c83ff1c27675e98ce28f4cc49a33ebb9 (patch) | |
| tree | 989b08a0d3016ac63e254ae44fcb7385bf9fc020 /extmod/modujson.c | |
| parent | e947e4eb580e080d37445240ec88610fc1787975 (diff) | |
| parent | 62b835ad7637c5336f210ab688289dc607bec661 (diff) | |
merged master
Diffstat (limited to 'extmod/modujson.c')
| -rw-r--r-- | extmod/modujson.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/extmod/modujson.c b/extmod/modujson.c index 6b24bf578..0f93ccb11 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); } @@ -89,9 +94,10 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) { return s->cur; } -STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { +STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) { 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 @@ -262,13 +268,18 @@ 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 after JSON. + // E.g., A UART is not closed after receiving an object; in load() we will + // return the first complete JSON object, while in loads() we will retain + // strict adherence to the buffer's complete semantic. + if (!return_first_json) { + while (unichar_isspace(S_CUR(s))) { + S_NEXT(s); + } + if (!S_END(s)) { + // unexpected chars + goto fail; + } } if (stack_top == MP_OBJ_NULL || stack.len != 0) { // not exactly 1 object @@ -280,6 +291,10 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { fail: mp_raise_ValueError(translate("syntax error in JSON")); } + +STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { + return _mod_ujson_load(stream_obj, true); +} STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load); STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { @@ -287,7 +302,7 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { const char *buf = mp_obj_str_get_data(obj, &len); vstr_t vstr = {len, len, (char*)buf, true}; mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL}; - return mod_ujson_load(MP_OBJ_FROM_PTR(&sio)); + return _mod_ujson_load(MP_OBJ_FROM_PTR(&sio), false); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads); |
