Skip to content

Commit 55f78bf

Browse files
authored
Merge pull request #2878 from WarriorOfWire/ujson-stream-protocol
ujson: work with mp stream protocol for fast & easy read
2 parents 801d965 + d8491f3 commit 55f78bf

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

extmod/modujson.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
5353
}
5454
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
5555

56+
#define JSON_DEBUG(...) (void)0
57+
// #define JSON_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
58+
59+
5660
// The function below implements a simple non-recursive JSON parser.
5761
//
5862
// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
@@ -80,6 +84,7 @@ typedef struct _ujson_stream_t {
8084

8185
STATIC byte ujson_stream_next(ujson_stream_t *s) {
8286
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
87+
JSON_DEBUG(" usjon_stream_next err:%2d cur: %c \n", s->errcode, s->cur);
8388
if (s->errcode != 0) {
8489
mp_raise_OSError(s->errcode);
8590
}
@@ -89,9 +94,10 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
8994
return s->cur;
9095
}
9196

92-
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
97+
STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) {
9398
const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ);
9499
ujson_stream_t s = {stream_obj, stream_p->read, 0, 0};
100+
JSON_DEBUG("got JSON stream\n");
95101
vstr_t vstr;
96102
vstr_init(&vstr, 8);
97103
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) {
262268
}
263269
}
264270
success:
265-
// eat trailing whitespace
266-
while (unichar_isspace(S_CUR(s))) {
267-
S_NEXT(s);
268-
}
269-
if (!S_END(s)) {
270-
// unexpected chars
271-
goto fail;
271+
// It is legal for a stream to have contents after JSON.
272+
// E.g., A UART is not closed after receiving an object; in load() we will
273+
// return the first complete JSON object, while in loads() we will retain
274+
// strict adherence to the buffer's complete semantic.
275+
if (!return_first_json) {
276+
while (unichar_isspace(S_CUR(s))) {
277+
S_NEXT(s);
278+
}
279+
if (!S_END(s)) {
280+
// unexpected chars
281+
goto fail;
282+
}
272283
}
273284
if (stack_top == MP_OBJ_NULL || stack.len != 0) {
274285
// not exactly 1 object
@@ -280,14 +291,18 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
280291
fail:
281292
mp_raise_ValueError(translate("syntax error in JSON"));
282293
}
294+
295+
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
296+
return _mod_ujson_load(stream_obj, true);
297+
}
283298
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
284299

285300
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
286301
size_t len;
287302
const char *buf = mp_obj_str_get_data(obj, &len);
288303
vstr_t vstr = {len, len, (char*)buf, true};
289304
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
290-
return mod_ujson_load(MP_OBJ_FROM_PTR(&sio));
305+
return _mod_ujson_load(MP_OBJ_FROM_PTR(&sio), false);
291306
}
292307
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
293308

ports/atmel-samd/common-hal/busio/UART.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545

4646
#include "samd/sercom.h"
4747

48+
#define UART_DEBUG(...) (void)0
49+
// #define UART_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
50+
4851
// Do-nothing callback needed so that usart_async code will enable rx interrupts.
4952
// See comment below re usart_async_register_callback()
5053
static void usart_async_rxc_callback(const struct usart_async_descriptor *const descr) {

shared-bindings/busio/UART.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#include "py/stream.h"
4040
#include "supervisor/shared/translate.h"
4141

42+
#define STREAM_DEBUG(...) (void)0
43+
// #define STREAM_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
44+
4245

4346
//| .. currentmodule:: busio
4447
//|
@@ -219,6 +222,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_
219222

220223
// These three methods are used by the shared stream methods.
221224
STATIC mp_uint_t busio_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
225+
STREAM_DEBUG("busio_uart_read stream %d\n", size);
222226
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
223227
check_for_deinit(self);
224228
byte *buf = buf_in;

0 commit comments

Comments
 (0)