@@ -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,44 @@ 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 ) {
88
+ (void ) size ; // Ignore size because we know it's always 1.
81
89
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 ;
90
+
91
+ if (s -> start == s -> end ) {
92
+ * errcode = 0 ;
93
+ mp_obj_t ret = mp_call_method_n_kw (1 , 0 , s -> python_readinto );
94
+ if (ret == mp_const_none ) {
95
+ * errcode = MP_EAGAIN ;
96
+ return MP_STREAM_ERROR ;
97
+ }
98
+ s -> start = 0 ;
99
+ s -> end = mp_obj_get_int (ret );
89
100
}
90
- return mp_obj_get_int (ret );
101
+
102
+ * ((uint8_t * )buf ) = ((uint8_t * ) s -> bytearray_obj .items )[s -> start ];
103
+ s -> start ++ ;
104
+ return 1 ;
91
105
}
92
106
93
107
STATIC mp_obj_t _mod_ujson_load (mp_obj_t stream_obj , bool return_first_json ) {
94
108
const mp_stream_p_t * stream_p = mp_proto_get (MP_QSTR_protocol_stream , stream_obj );
95
109
ujson_stream_t s ;
110
+ uint8_t character_buffer [CIRCUITPY_JSON_READ_CHUNK_SIZE ];
96
111
if (stream_p == NULL ) {
112
+ s .start = 0 ;
113
+ s .end = 0 ;
97
114
mp_load_method (stream_obj , MP_QSTR_readinto , s .python_readinto );
98
115
s .bytearray_obj .base .type = & mp_type_bytearray ;
99
116
s .bytearray_obj .typecode = BYTEARRAY_TYPECODE ;
117
+ s .bytearray_obj .len = CIRCUITPY_JSON_READ_CHUNK_SIZE ;
100
118
s .bytearray_obj .free = 0 ;
101
- // len and items are set at read time
119
+ s . bytearray_obj . items = character_buffer ;
102
120
s .python_readinto [2 ] = MP_OBJ_FROM_PTR (& s .bytearray_obj );
103
121
s .stream_obj = & s ;
104
122
s .read = ujson_python_readinto ;
0 commit comments