25
25
*/
26
26
27
27
#include <unistd.h> // for ssize_t
28
- #include <string.h>
29
-
30
- #include "py/mpconfig.h"
31
- #if MICROPY_PY_COLLECTIONS_DEQUE
32
28
33
29
#include "py/runtime.h"
34
30
31
+ #if MICROPY_PY_COLLECTIONS_DEQUE
32
+
35
33
typedef struct _mp_obj_deque_t {
36
34
mp_obj_base_t base ;
37
35
size_t alloc ;
@@ -42,15 +40,15 @@ typedef struct _mp_obj_deque_t {
42
40
#define FLAG_CHECK_OVERFLOW 1
43
41
} mp_obj_deque_t ;
44
42
43
+ static mp_obj_t mp_obj_deque_append (mp_obj_t self_in , mp_obj_t arg );
44
+ static mp_obj_t mp_obj_deque_extend (mp_obj_t self_in , mp_obj_t arg_in );
45
+ #if MICROPY_PY_COLLECTIONS_DEQUE_ITER
46
+ static mp_obj_t mp_obj_new_deque_it (mp_obj_t deque , mp_obj_iter_buf_t * iter_buf );
47
+ #endif
48
+
45
49
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
50
mp_arg_check_num (n_args , n_kw , 2 , 3 , false);
47
51
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
52
// Protect against -1 leading to zero-length allocation and bad array access
55
53
mp_int_t maxlen = mp_obj_get_int (args [1 ]);
56
54
if (maxlen < 0 ) {
@@ -66,21 +64,27 @@ static mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t
66
64
o -> flags = mp_obj_get_int (args [2 ]);
67
65
}
68
66
67
+ mp_obj_deque_extend (MP_OBJ_FROM_PTR (o ), args [0 ]);
68
+
69
69
return MP_OBJ_FROM_PTR (o );
70
70
}
71
71
72
+ static size_t deque_len (mp_obj_deque_t * self ) {
73
+ ssize_t len = self -> i_put - self -> i_get ;
74
+ if (len < 0 ) {
75
+ len += self -> alloc ;
76
+ }
77
+ return len ;
78
+ }
79
+
72
80
static mp_obj_t deque_unary_op (mp_unary_op_t op , mp_obj_t self_in ) {
73
81
mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
74
82
switch (op ) {
75
83
case MP_UNARY_OP_BOOL :
76
84
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
- }
85
+ case MP_UNARY_OP_LEN :
86
+ return MP_OBJ_NEW_SMALL_INT (deque_len (self ));
87
+
84
88
#if MICROPY_PY_SYS_GETSIZEOF
85
89
case MP_UNARY_OP_SIZEOF : {
86
90
size_t sz = sizeof (* self ) + sizeof (mp_obj_t ) * self -> alloc ;
@@ -117,6 +121,45 @@ static mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) {
117
121
}
118
122
static MP_DEFINE_CONST_FUN_OBJ_2 (deque_append_obj , mp_obj_deque_append ) ;
119
123
124
+ static mp_obj_t mp_obj_deque_appendleft (mp_obj_t self_in , mp_obj_t arg ) {
125
+ mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
126
+
127
+ size_t new_i_get = self -> i_get - 1 ;
128
+ if (self -> i_get == 0 ) {
129
+ new_i_get = self -> alloc - 1 ;
130
+ }
131
+
132
+ if (self -> flags & FLAG_CHECK_OVERFLOW && new_i_get == self -> i_put ) {
133
+ mp_raise_msg (& mp_type_IndexError , MP_ERROR_TEXT ("full" ));
134
+ }
135
+
136
+ self -> i_get = new_i_get ;
137
+ self -> items [self -> i_get ] = arg ;
138
+
139
+ // overwriting first element in deque
140
+ if (self -> i_put == new_i_get ) {
141
+ if (self -> i_put == 0 ) {
142
+ self -> i_put = self -> alloc - 1 ;
143
+ } else {
144
+ self -> i_put -- ;
145
+ }
146
+ }
147
+
148
+ return mp_const_none ;
149
+ }
150
+ static MP_DEFINE_CONST_FUN_OBJ_2 (deque_appendleft_obj , mp_obj_deque_appendleft ) ;
151
+
152
+ static mp_obj_t mp_obj_deque_extend (mp_obj_t self_in , mp_obj_t arg_in ) {
153
+ mp_obj_iter_buf_t iter_buf ;
154
+ mp_obj_t iter = mp_getiter (arg_in , & iter_buf );
155
+ mp_obj_t item ;
156
+ while ((item = mp_iternext (iter )) != MP_OBJ_STOP_ITERATION ) {
157
+ mp_obj_deque_append (self_in , item );
158
+ }
159
+ return mp_const_none ;
160
+ }
161
+ static MP_DEFINE_CONST_FUN_OBJ_2 (deque_extend_obj , mp_obj_deque_extend ) ;
162
+
120
163
static mp_obj_t deque_popleft (mp_obj_t self_in ) {
121
164
mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
122
165
@@ -135,6 +178,51 @@ static mp_obj_t deque_popleft(mp_obj_t self_in) {
135
178
}
136
179
static MP_DEFINE_CONST_FUN_OBJ_1 (deque_popleft_obj , deque_popleft ) ;
137
180
181
+ static mp_obj_t deque_pop (mp_obj_t self_in ) {
182
+ mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
183
+
184
+ if (self -> i_get == self -> i_put ) {
185
+ mp_raise_msg (& mp_type_IndexError , MP_ERROR_TEXT ("empty" ));
186
+ }
187
+
188
+ if (self -> i_put == 0 ) {
189
+ self -> i_put = self -> alloc - 1 ;
190
+ } else {
191
+ self -> i_put -- ;
192
+ }
193
+
194
+ mp_obj_t ret = self -> items [self -> i_put ];
195
+ self -> items [self -> i_put ] = MP_OBJ_NULL ;
196
+
197
+ return ret ;
198
+ }
199
+ static MP_DEFINE_CONST_FUN_OBJ_1 (deque_pop_obj , deque_pop ) ;
200
+
201
+ #if MICROPY_PY_COLLECTIONS_DEQUE_SUBSCR
202
+ static mp_obj_t deque_subscr (mp_obj_t self_in , mp_obj_t index , mp_obj_t value ) {
203
+ if (value == MP_OBJ_NULL ) {
204
+ // delete not supported, fall back to mp_obj_subscr() error message
205
+ return MP_OBJ_NULL ;
206
+ }
207
+ mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
208
+
209
+ size_t offset = mp_get_index (self -> base .type , deque_len (self ), index , false);
210
+ size_t index_val = self -> i_get + offset ;
211
+ if (index_val > self -> alloc ) {
212
+ index_val -= self -> alloc ;
213
+ }
214
+
215
+ if (value == MP_OBJ_SENTINEL ) {
216
+ // load
217
+ return self -> items [index_val ];
218
+ } else {
219
+ // store into deque
220
+ self -> items [index_val ] = value ;
221
+ return mp_const_none ;
222
+ }
223
+ }
224
+ #endif
225
+
138
226
#if 0
139
227
static mp_obj_t deque_clear (mp_obj_t self_in ) {
140
228
mp_obj_deque_t * self = MP_OBJ_TO_PTR (self_in );
@@ -147,21 +235,80 @@ static MP_DEFINE_CONST_FUN_OBJ_1(deque_clear_obj, deque_clear);
147
235
148
236
static const mp_rom_map_elem_t deque_locals_dict_table [] = {
149
237
{ MP_ROM_QSTR (MP_QSTR_append ), MP_ROM_PTR (& deque_append_obj ) },
238
+ { MP_ROM_QSTR (MP_QSTR_appendleft ), MP_ROM_PTR (& deque_appendleft_obj ) },
239
+ { MP_ROM_QSTR (MP_QSTR_extend ), MP_ROM_PTR (& deque_extend_obj ) },
150
240
#if 0
151
241
{ MP_ROM_QSTR (MP_QSTR_clear ), MP_ROM_PTR (& deque_clear_obj ) },
152
242
#endif
243
+ { MP_ROM_QSTR (MP_QSTR_pop ), MP_ROM_PTR (& deque_pop_obj ) },
153
244
{ MP_ROM_QSTR (MP_QSTR_popleft ), MP_ROM_PTR (& deque_popleft_obj ) },
154
245
};
155
246
156
247
static MP_DEFINE_CONST_DICT (deque_locals_dict , deque_locals_dict_table ) ;
157
248
249
+ #if MICROPY_PY_COLLECTIONS_DEQUE_ITER
250
+ #define DEQUE_TYPE_FLAGS MP_TYPE_FLAG_ITER_IS_GETITER
251
+ #define DEQUE_TYPE_ITER iter, mp_obj_new_deque_it,
252
+ #else
253
+ #define DEQUE_TYPE_FLAGS MP_TYPE_FLAG_NONE
254
+ #define DEQUE_TYPE_ITER
255
+ #endif
256
+
257
+ #if MICROPY_PY_COLLECTIONS_DEQUE_SUBSCR
258
+ #define DEQUE_TYPE_SUBSCR subscr, deque_subscr,
259
+ #else
260
+ #define DEQUE_TYPE_SUBSCR
261
+ #endif
262
+
158
263
MP_DEFINE_CONST_OBJ_TYPE (
159
264
mp_type_deque ,
160
265
MP_QSTR_deque ,
161
- MP_TYPE_FLAG_NONE ,
266
+ MP_TYPE_FLAG_ITER_IS_GETITER ,
162
267
make_new , deque_make_new ,
163
268
unary_op , deque_unary_op ,
269
+ DEQUE_TYPE_SUBSCR
270
+ DEQUE_TYPE_ITER
164
271
locals_dict , & deque_locals_dict
165
272
);
166
273
274
+ /******************************************************************************/
275
+ /* deque iterator */
276
+
277
+ #if MICROPY_PY_COLLECTIONS_DEQUE_ITER
278
+
279
+ typedef struct _mp_obj_deque_it_t {
280
+ mp_obj_base_t base ;
281
+ mp_fun_1_t iternext ;
282
+ mp_obj_t deque ;
283
+ size_t cur ;
284
+ } mp_obj_deque_it_t ;
285
+
286
+ static mp_obj_t deque_it_iternext (mp_obj_t self_in ) {
287
+ mp_obj_deque_it_t * self = MP_OBJ_TO_PTR (self_in );
288
+ mp_obj_deque_t * deque = MP_OBJ_TO_PTR (self -> deque );
289
+ if (self -> cur != deque -> i_put ) {
290
+ mp_obj_t o_out = deque -> items [self -> cur ];
291
+ if (++ self -> cur == deque -> alloc ) {
292
+ self -> cur = 0 ;
293
+ }
294
+ return o_out ;
295
+ } else {
296
+ return MP_OBJ_STOP_ITERATION ;
297
+ }
298
+ }
299
+
300
+ static mp_obj_t mp_obj_new_deque_it (mp_obj_t deque , mp_obj_iter_buf_t * iter_buf ) {
301
+ mp_obj_deque_t * deque_ = MP_OBJ_TO_PTR (deque );
302
+ size_t i_get = deque_ -> i_get ;
303
+ assert (sizeof (mp_obj_deque_it_t ) <= sizeof (mp_obj_iter_buf_t ));
304
+ mp_obj_deque_it_t * o = (mp_obj_deque_it_t * )iter_buf ;
305
+ o -> base .type = & mp_type_polymorph_iter ;
306
+ o -> iternext = deque_it_iternext ;
307
+ o -> deque = deque ;
308
+ o -> cur = i_get ;
309
+ return MP_OBJ_FROM_PTR (o );
310
+ }
311
+
312
+ #endif
313
+
167
314
#endif // MICROPY_PY_COLLECTIONS_DEQUE
0 commit comments