Merge pull request #2878 from WarriorOfWire/ujson-stream-protocol
ujson: work with mp stream protocol for fast & easy read
This commit is contained in:
commit
55f78bfb70
@ -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);
|
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 function below implements a simple non-recursive JSON parser.
|
||||||
//
|
//
|
||||||
// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
|
// 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) {
|
STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
||||||
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
|
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) {
|
if (s->errcode != 0) {
|
||||||
mp_raise_OSError(s->errcode);
|
mp_raise_OSError(s->errcode);
|
||||||
}
|
}
|
||||||
@ -89,9 +94,10 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
|||||||
return s->cur;
|
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);
|
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};
|
ujson_stream_t s = {stream_obj, stream_p->read, 0, 0};
|
||||||
|
JSON_DEBUG("got JSON stream\n");
|
||||||
vstr_t vstr;
|
vstr_t vstr;
|
||||||
vstr_init(&vstr, 8);
|
vstr_init(&vstr, 8);
|
||||||
mp_obj_list_t stack; // we use a list as a simple stack for nested JSON
|
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:
|
success:
|
||||||
// eat trailing whitespace
|
// It is legal for a stream to have contents after JSON.
|
||||||
while (unichar_isspace(S_CUR(s))) {
|
// E.g., A UART is not closed after receiving an object; in load() we will
|
||||||
S_NEXT(s);
|
// return the first complete JSON object, while in loads() we will retain
|
||||||
}
|
// strict adherence to the buffer's complete semantic.
|
||||||
if (!S_END(s)) {
|
if (!return_first_json) {
|
||||||
// unexpected chars
|
while (unichar_isspace(S_CUR(s))) {
|
||||||
goto fail;
|
S_NEXT(s);
|
||||||
|
}
|
||||||
|
if (!S_END(s)) {
|
||||||
|
// unexpected chars
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (stack_top == MP_OBJ_NULL || stack.len != 0) {
|
if (stack_top == MP_OBJ_NULL || stack.len != 0) {
|
||||||
// not exactly 1 object
|
// not exactly 1 object
|
||||||
@ -280,6 +291,10 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
|
|||||||
fail:
|
fail:
|
||||||
mp_raise_ValueError(translate("syntax error in JSON"));
|
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_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
|
||||||
|
|
||||||
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
|
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);
|
const char *buf = mp_obj_str_get_data(obj, &len);
|
||||||
vstr_t vstr = {len, len, (char*)buf, true};
|
vstr_t vstr = {len, len, (char*)buf, true};
|
||||||
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
|
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);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
|
||||||
|
|
||||||
|
@ -45,6 +45,9 @@
|
|||||||
|
|
||||||
#include "samd/sercom.h"
|
#include "samd/sercom.h"
|
||||||
|
|
||||||
|
#define UART_DEBUG(...) (void)0
|
||||||
|
// #define UART_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
|
||||||
|
|
||||||
// Do-nothing callback needed so that usart_async code will enable rx interrupts.
|
// Do-nothing callback needed so that usart_async code will enable rx interrupts.
|
||||||
// See comment below re usart_async_register_callback()
|
// See comment below re usart_async_register_callback()
|
||||||
static void usart_async_rxc_callback(const struct usart_async_descriptor *const descr) {
|
static void usart_async_rxc_callback(const struct usart_async_descriptor *const descr) {
|
||||||
|
@ -39,6 +39,9 @@
|
|||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate.h"
|
||||||
|
|
||||||
|
#define STREAM_DEBUG(...) (void)0
|
||||||
|
// #define STREAM_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
//| .. currentmodule:: busio
|
//| .. currentmodule:: busio
|
||||||
//|
|
//|
|
||||||
@ -219,6 +222,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_
|
|||||||
|
|
||||||
// These three methods are used by the shared stream methods.
|
// These three methods are used by the shared stream methods.
|
||||||
STATIC mp_uint_t busio_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
|
STATIC mp_uint_t busio_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
|
||||||
|
STREAM_DEBUG("busio_uart_read stream %d\n", size);
|
||||||
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||||
check_for_deinit(self);
|
check_for_deinit(self);
|
||||||
byte *buf = buf_in;
|
byte *buf = buf_in;
|
||||||
|
Loading…
Reference in New Issue
Block a user