32
32
33
33
#include "py/runtime.h"
34
34
35
+ STATIC mp_obj_t mp_obj_new_deque_iterator (mp_obj_t deque , size_t cur , mp_obj_iter_buf_t * iter_buf );
36
+ STATIC mp_obj_t mp_obj_deque_append (mp_obj_t self_in , mp_obj_t arg );
37
+
38
+
35
39
typedef struct _mp_obj_deque_t {
36
40
mp_obj_base_t base ;
37
41
size_t alloc ;
@@ -42,15 +46,18 @@ typedef struct _mp_obj_deque_t {
42
46
#define FLAG_CHECK_OVERFLOW 1
43
47
} mp_obj_deque_t ;
44
48
49
+ STATIC mp_obj_t deque_extend_from_iter (mp_obj_t deque , mp_obj_t iterable ) {
50
+ mp_obj_t iter = mp_getiter (iterable , NULL );
51
+ mp_obj_t item ;
52
+ while ((item = mp_iternext (iter )) != MP_OBJ_STOP_ITERATION ) {
53
+ mp_obj_deque_append (deque , item );
54
+ }
55
+ return deque ;
56
+ }
57
+
45
58
STATIC mp_obj_t deque_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args ) {
46
59
mp_arg_check_num (n_args , n_kw , 2 , 3 , false);
47
60
48
- /* Initialization from existing sequence is not supported, so an empty
49
- tuple must be passed as such. */
50
- if (args [0 ] != mp_const_empty_tuple ) {
51
- mp_raise_ValueError (NULL );
52
- }
53
-
54
61
// Protect against -1 leading to zero-length allocation and bad array access
55
62
mp_int_t maxlen = mp_obj_get_int (args [1 ]);
56
63
if (maxlen < 0 ) {
@@ -66,21 +73,27 @@ STATIC mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t
66
73
o -> flags = mp_obj_get_int (args [2 ]);
67
74
}
68
75
76
+ deque_extend_from_iter (MP_OBJ_FROM_PTR (o ), args [0 ]);
77
+
69
78
return MP_OBJ_FROM_PTR (o );
70
79
}
71
80
81
+ STATIC size_t deque_len (mp_obj_deque_t * self ) {
82
+ ssize_t len = self -> i_put - self -> i_get ;
83
+ if (len < 0 ) {
84
+ len += self -> alloc ;
85
+ }
86
+ return len ;
87
+ }
88
+
72
89
STATIC mp_obj_t deque_unary_op (mp_unary_op_t op , mp_obj_t self_in ) {
73
90
mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
74
91
switch (op ) {
75
92
case MP_UNARY_OP_BOOL :
76
93
return mp_obj_new_bool (self -> i_get != self -> i_put );
77
- case MP_UNARY_OP_LEN : {
78
- ssize_t len = self -> i_put - self -> i_get ;
79
- if (len < 0 ) {
80
- len += self -> alloc ;
81
- }
82
- return MP_OBJ_NEW_SMALL_INT (len );
83
- }
94
+ case MP_UNARY_OP_LEN :
95
+ return MP_OBJ_NEW_SMALL_INT (deque_len (self ));
96
+
84
97
#if MICROPY_PY_SYS_GETSIZEOF
85
98
case MP_UNARY_OP_SIZEOF : {
86
99
size_t sz = sizeof (* self ) + sizeof (mp_obj_t ) * self -> alloc ;
@@ -117,6 +130,41 @@ STATIC mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) {
117
130
}
118
131
STATIC MP_DEFINE_CONST_FUN_OBJ_2 (deque_append_obj , mp_obj_deque_append );
119
132
133
+ STATIC mp_obj_t mp_obj_deque_appendleft (mp_obj_t self_in , mp_obj_t arg ) {
134
+ mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
135
+
136
+ size_t new_i_get = self -> i_get - 1 ;
137
+ if (self -> i_get == 0 ) {
138
+ new_i_get = self -> alloc - 1 ;
139
+ }
140
+
141
+ if (self -> flags & FLAG_CHECK_OVERFLOW && new_i_get == self -> i_put ) {
142
+ mp_raise_msg (& mp_type_IndexError , MP_ERROR_TEXT ("full" ));
143
+ }
144
+
145
+ self -> i_get = new_i_get ;
146
+ self -> items [self -> i_get ] = arg ;
147
+
148
+ // overwriting first element in deque
149
+ if (self -> i_put == new_i_get ) {
150
+ if (self -> i_put == 0 ) {
151
+ self -> i_put = self -> alloc - 1 ;
152
+ } else {
153
+ self -> i_put -- ;
154
+ }
155
+ }
156
+
157
+ return mp_const_none ;
158
+ }
159
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (deque_appendleft_obj , mp_obj_deque_appendleft );
160
+
161
+ STATIC mp_obj_t deque_extend (mp_obj_t self_in , mp_obj_t arg_in ) {
162
+ deque_extend_from_iter (self_in , arg_in );
163
+ return mp_const_none ;
164
+ }
165
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (deque_extend_obj , deque_extend );
166
+
167
+
120
168
STATIC mp_obj_t deque_popleft (mp_obj_t self_in ) {
121
169
mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
122
170
@@ -135,6 +183,54 @@ STATIC mp_obj_t deque_popleft(mp_obj_t self_in) {
135
183
}
136
184
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (deque_popleft_obj , deque_popleft );
137
185
186
+ STATIC mp_obj_t deque_pop (mp_obj_t self_in ) {
187
+ mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
188
+
189
+ if (self -> i_get == self -> i_put ) {
190
+ mp_raise_msg (& mp_type_IndexError , MP_ERROR_TEXT ("empty" ));
191
+ }
192
+
193
+ if (self -> i_put == 0 ) {
194
+ self -> i_put = self -> alloc - 1 ;
195
+ } else {
196
+ self -> i_put -- ;
197
+ }
198
+
199
+ mp_obj_t ret = self -> items [self -> i_put ];
200
+ self -> items [self -> i_put ] = MP_OBJ_NULL ;
201
+
202
+ return ret ;
203
+ }
204
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (deque_pop_obj , deque_pop );
205
+
206
+ STATIC mp_obj_t deque_getiter (mp_obj_t o_in , mp_obj_iter_buf_t * iter_buf ) {
207
+ mp_obj_deque_t * deque = MP_OBJ_TO_PTR (o_in );
208
+ return mp_obj_new_deque_iterator (o_in , deque -> i_get , iter_buf );
209
+ }
210
+
211
+ STATIC mp_obj_t deque_subscr (mp_obj_t self_in , mp_obj_t index , mp_obj_t value ) {
212
+ if (value == MP_OBJ_NULL ) {
213
+ // delete not supported, fall back to mp_obj_subscr() error message
214
+ return MP_OBJ_NULL ;
215
+ }
216
+ mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
217
+
218
+ size_t offset = mp_get_index (self -> base .type , deque_len (self ), index , false);
219
+ size_t index_val = self -> i_get + offset ;
220
+ if (index_val > self -> alloc ) {
221
+ index_val -= self -> alloc ;
222
+ }
223
+
224
+ if (value == MP_OBJ_SENTINEL ) {
225
+ // load
226
+ return self -> items [index_val ];
227
+ } else {
228
+ // store into deque
229
+ self -> items [index_val ] = value ;
230
+ return mp_const_none ;
231
+ }
232
+ }
233
+
138
234
#if 0
139
235
STATIC mp_obj_t deque_clear (mp_obj_t self_in ) {
140
236
mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
@@ -147,9 +243,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(deque_clear_obj, deque_clear);
147
243
148
244
STATIC const mp_rom_map_elem_t deque_locals_dict_table [] = {
149
245
{ MP_ROM_QSTR (MP_QSTR_append ), MP_ROM_PTR (& deque_append_obj ) },
246
+ { MP_ROM_QSTR (MP_QSTR_appendleft ), MP_ROM_PTR (& deque_appendleft_obj ) },
247
+ { MP_ROM_QSTR (MP_QSTR_extend ), MP_ROM_PTR (& deque_extend_obj ) },
150
248
#if 0
151
249
{ MP_ROM_QSTR (MP_QSTR_clear ), MP_ROM_PTR (& deque_clear_obj ) },
152
250
#endif
251
+ { MP_ROM_QSTR (MP_QSTR_pop ), MP_ROM_PTR (& deque_pop_obj ) },
153
252
{ MP_ROM_QSTR (MP_QSTR_popleft ), MP_ROM_PTR (& deque_popleft_obj ) },
154
253
};
155
254
@@ -158,10 +257,46 @@ STATIC MP_DEFINE_CONST_DICT(deque_locals_dict, deque_locals_dict_table);
158
257
MP_DEFINE_CONST_OBJ_TYPE (
159
258
mp_type_deque ,
160
259
MP_QSTR_deque ,
161
- MP_TYPE_FLAG_NONE ,
260
+ MP_TYPE_FLAG_ITER_IS_GETITER ,
162
261
make_new , deque_make_new ,
163
262
unary_op , deque_unary_op ,
263
+ subscr , deque_subscr ,
264
+ iter , deque_getiter ,
164
265
locals_dict , & deque_locals_dict
165
266
);
166
267
268
+ /******************************************************************************/
269
+ /* deque iterator */
270
+ typedef struct _mp_obj_deque_it_t {
271
+ mp_obj_base_t base ;
272
+ mp_fun_1_t iternext ;
273
+ mp_obj_t deque ;
274
+ size_t cur ;
275
+ } mp_obj_deque_it_t ;
276
+
277
+ STATIC mp_obj_t deque_it_iternext (mp_obj_t self_in ) {
278
+ mp_obj_deque_it_t * self = MP_OBJ_TO_PTR (self_in );
279
+ mp_obj_deque_t * deque = MP_OBJ_TO_PTR (self -> deque );
280
+ if (self -> cur != deque -> i_put ) {
281
+ mp_obj_t o_out = deque -> items [self -> cur ];
282
+
283
+ if (++ self -> cur == deque -> alloc ) {
284
+ self -> cur = 0 ;
285
+ }
286
+ return o_out ;
287
+ } else {
288
+ return MP_OBJ_STOP_ITERATION ;
289
+ }
290
+ }
291
+
292
+ mp_obj_t mp_obj_new_deque_iterator (mp_obj_t deque , size_t i_get , mp_obj_iter_buf_t * iter_buf ) {
293
+ assert (sizeof (mp_obj_deque_it_t ) <= sizeof (mp_obj_iter_buf_t ));
294
+ mp_obj_deque_it_t * o = (mp_obj_deque_it_t * )iter_buf ;
295
+ o -> base .type = & mp_type_polymorph_iter ;
296
+ o -> iternext = deque_it_iternext ;
297
+ o -> deque = deque ;
298
+ o -> cur = i_get ;
299
+ return MP_OBJ_FROM_PTR (o );
300
+ }
301
+
167
302
#endif // MICROPY_PY_COLLECTIONS_DEQUE
0 commit comments