@@ -57,6 +57,8 @@ typedef struct _ujson_stream_t {
5757 int errcode ;
5858 mp_obj_t python_readinto [2 + 1 ];
5959 mp_obj_array_t bytearray_obj ;
60+ size_t start ;
61+ size_t end ;
6062 byte cur ;
6163} ujson_stream_t ;
6264
@@ -77,28 +79,43 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
7779 return s -> cur ;
7880}
7981
82+ // We read from an object's `readinto` method in chunks larger than the json
83+ // parser needs to reduce the number of function calls done.
84+
85+ #define CIRCUITPY_JSON_READ_CHUNK_SIZE 64
86+
8087STATIC mp_uint_t ujson_python_readinto (mp_obj_t obj , void * buf , mp_uint_t size , int * errcode ) {
8188 ujson_stream_t * s = obj ;
82- s -> bytearray_obj .items = buf ;
83- s -> bytearray_obj .len = size ;
84- * errcode = 0 ;
85- mp_obj_t ret = mp_call_method_n_kw (1 , 0 , s -> python_readinto );
86- if (ret == mp_const_none ) {
87- * errcode = MP_EAGAIN ;
88- return MP_STREAM_ERROR ;
89+
90+ if (s -> start == s -> end ) {
91+ * errcode = 0 ;
92+ mp_obj_t ret = mp_call_method_n_kw (1 , 0 , s -> python_readinto );
93+ if (ret == mp_const_none ) {
94+ * errcode = MP_EAGAIN ;
95+ return MP_STREAM_ERROR ;
96+ }
97+ s -> start = 0 ;
98+ s -> end = mp_obj_get_int (ret );
8999 }
90- return mp_obj_get_int (ret );
100+
101+ * ((uint8_t * )buf ) = ((uint8_t * ) s -> bytearray_obj .items )[s -> start ];
102+ s -> start ++ ;
103+ return 1 ;
91104}
92105
93106STATIC mp_obj_t _mod_ujson_load (mp_obj_t stream_obj , bool return_first_json ) {
94107 const mp_stream_p_t * stream_p = mp_proto_get (MP_QSTR_protocol_stream , stream_obj );
95108 ujson_stream_t s ;
109+ uint8_t character_buffer [CIRCUITPY_JSON_READ_CHUNK_SIZE ];
96110 if (stream_p == NULL ) {
111+ s .start = 0 ;
112+ s .end = 0 ;
97113 mp_load_method (stream_obj , MP_QSTR_readinto , s .python_readinto );
98114 s .bytearray_obj .base .type = & mp_type_bytearray ;
99115 s .bytearray_obj .typecode = BYTEARRAY_TYPECODE ;
116+ s .bytearray_obj .len = CIRCUITPY_JSON_READ_CHUNK_SIZE ;
100117 s .bytearray_obj .free = 0 ;
101- // len and items are set at read time
118+ s . bytearray_obj . items = character_buffer ;
102119 s .python_readinto [2 ] = MP_OBJ_FROM_PTR (& s .bytearray_obj );
103120 s .stream_obj = & s ;
104121 s .read = ujson_python_readinto ;
0 commit comments