@@ -57,6 +57,8 @@ typedef struct _ujson_stream_t {
57
57
int errcode ;
58
58
mp_obj_t python_readinto [2 + 1 ];
59
59
mp_obj_array_t bytearray_obj ;
60
+ size_t start ;
61
+ size_t end ;
60
62
byte cur ;
61
63
} ujson_stream_t ;
62
64
@@ -77,28 +79,43 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
77
79
return s -> cur ;
78
80
}
79
81
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
+
80
87
STATIC mp_uint_t ujson_python_readinto (mp_obj_t obj , void * buf , mp_uint_t size , int * errcode ) {
81
88
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 );
89
99
}
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 ;
91
104
}
92
105
93
106
STATIC mp_obj_t _mod_ujson_load (mp_obj_t stream_obj , bool return_first_json ) {
94
107
const mp_stream_p_t * stream_p = mp_proto_get (MP_QSTR_protocol_stream , stream_obj );
95
108
ujson_stream_t s ;
109
+ uint8_t character_buffer [CIRCUITPY_JSON_READ_CHUNK_SIZE ];
96
110
if (stream_p == NULL ) {
111
+ s .start = 0 ;
112
+ s .end = 0 ;
97
113
mp_load_method (stream_obj , MP_QSTR_readinto , s .python_readinto );
98
114
s .bytearray_obj .base .type = & mp_type_bytearray ;
99
115
s .bytearray_obj .typecode = BYTEARRAY_TYPECODE ;
116
+ s .bytearray_obj .len = CIRCUITPY_JSON_READ_CHUNK_SIZE ;
100
117
s .bytearray_obj .free = 0 ;
101
- // len and items are set at read time
118
+ s . bytearray_obj . items = character_buffer ;
102
119
s .python_readinto [2 ] = MP_OBJ_FROM_PTR (& s .bytearray_obj );
103
120
s .stream_obj = & s ;
104
121
s .read = ujson_python_readinto ;
0 commit comments