Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersLists.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3/* This helpers is used to work with lists.
4
5*/
6
7// This file is included from another C file, help IDEs to still parse it on
8// its own.
9#ifdef __IDE_ONLY__
10#include "nuitka/prelude.h"
11#endif
12
13// #include "richcomparisons.h"
14
15static PyObject *Nuitka_LongFromCLong(long ival);
16
17#ifdef Py_GIL_DISABLED
18typedef struct {
19 Py_ssize_t allocated;
20 PyObject *ob_item[];
21} _PyListArray;
22
23static _PyListArray *Nuitka_AllocateListArray(size_t capacity) {
24 if (unlikely(capacity > PY_SSIZE_T_MAX / sizeof(PyObject *) - 1)) {
25 return NULL;
26 }
27
28 // TODO: API call to be removed.
29 _PyListArray *list_array = PyMem_Malloc(sizeof(_PyListArray) + capacity * sizeof(PyObject *));
30
31 if (unlikely(list_array == NULL)) {
32 return NULL;
33 }
34
35 list_array->allocated = capacity;
36 return list_array;
37}
38
39// spell-checker: ignore use_qsbr
40static void Nuitka_FreeListArray(PyObject **items, bool use_qsbr) {
41 _PyListArray *array = _Py_CONTAINER_OF(items, _PyListArray, ob_item);
42
43 if (use_qsbr) {
44 NuitkaMem_FreeDelayed(array);
45 } else {
46 NuitkaMem_Free(array);
47 }
48}
49
50#endif
51
52#if NUITKA_LIST_HAS_FREELIST
53
54PyObject *MAKE_LIST_EMPTY(PyThreadState *tstate, Py_ssize_t size) {
55 assert(size >= 0);
56
57#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
58 return PyList_New(size);
59#else
60 // This is the CPython name, spell-checker: ignore numfree
61
62#if PYTHON_VERSION < 0x3d0
63 PyListObject **items = tstate->interp->list.free_list;
64 int *numfree = &tstate->interp->list.numfree;
65#else
66 struct _Py_object_freelists *freelists = _Nuitka_object_freelists_GET(tstate);
67 struct _Py_list_freelist *state = &freelists->lists;
68 PyListObject **items = state->items;
69 int *numfree = &state->numfree;
70#endif
71 assert(*numfree >= 0);
72 PyListObject *result_list;
73
74 if (*numfree) {
75 (*numfree) -= 1;
76 result_list = items[*numfree];
77
78 Nuitka_Py_NewReference((PyObject *)result_list);
79 } else {
80 result_list = (PyListObject *)Nuitka_GC_New(&PyList_Type);
81 }
82
83 // Elements are allocated separately.
84 if (size > 0) {
85#ifdef Py_GIL_DISABLED
86 _PyListArray *list_array = Nuitka_AllocateListArray(size);
87
88 if (unlikely(list_array == NULL)) {
89 Py_DECREF(result_list);
90 return PyErr_NoMemory();
91 }
92#else
93 result_list->ob_item = (PyObject **)NuitkaMem_Calloc(size, sizeof(PyObject *));
94
95 if (unlikely(result_list->ob_item == NULL)) {
96 Py_DECREF(result_list);
97 return PyErr_NoMemory();
98 }
99#endif
100 } else {
101 result_list->ob_item = NULL;
102 }
103
104 Py_SET_SIZE(result_list, size);
105 result_list->allocated = size;
106
107 Nuitka_GC_Track(result_list);
108
109 return (PyObject *)result_list;
110#endif
111}
112#endif
113
114PyObject *LIST_COPY(PyThreadState *tstate, PyObject *list) {
115 CHECK_OBJECT(list);
116 assert(PyList_CheckExact(list));
117
118 Py_ssize_t size = PyList_GET_SIZE(list);
119 PyObject *result = MAKE_LIST_EMPTY(tstate, size);
120
121 if (unlikely(result == NULL)) {
122 return NULL;
123 }
124
125 for (Py_ssize_t i = 0; i < size; i++) {
126 PyObject *item = PyList_GET_ITEM(list, i);
127 Py_INCREF(item);
128 PyList_SET_ITEM(result, i, item);
129 }
130
131 return result;
132}
133
134static bool LIST_RESIZE(PyListObject *list, Py_ssize_t new_size) {
135 CHECK_OBJECT(list);
136 assert(new_size >= 0);
137
138 Py_ssize_t allocated = list->allocated;
139
140 if (allocated >= new_size && new_size >= (allocated >> 1)) {
141 Py_SET_SIZE(list, new_size);
142
143 return true;
144 }
145
146 size_t new_allocated;
147
148 if (new_size == 0) {
149 new_allocated = 0;
150 } else {
151 new_allocated = ((size_t)new_size + (new_size >> 3) + 6) & ~(size_t)3;
152 assert(new_allocated >= (size_t)new_size);
153 }
154
155#ifdef Py_GIL_DISABLED
156 _PyListArray *array = Nuitka_AllocateListArray(new_allocated);
157
158 if (array == NULL) {
159 PyErr_NoMemory();
160 return -1;
161 }
162 PyObject **old_items = list->ob_item;
163 if (list->ob_item != NULL) {
164 size_t num_allocated_bytes;
165 if (new_allocated < (size_t)allocated) {
166 num_allocated_bytes = new_allocated * sizeof(PyObject *);
167 } else {
168 num_allocated_bytes = allocated * sizeof(PyObject *);
169 }
170 memcpy(array->ob_item, list->ob_item, num_allocated_bytes);
171 }
172 if (new_allocated > (size_t)allocated) {
173 memset(array->ob_item + allocated, 0, sizeof(PyObject *) * (new_allocated - allocated));
174 }
175 _Py_atomic_store_ptr_release(&list->ob_item, &array->ob_item);
176 list->allocated = new_allocated;
177 Py_SET_SIZE(list, new_size);
178 if (old_items != NULL) {
179 Nuitka_FreeListArray(old_items, _PyObject_GC_IS_SHARED(list));
180 }
181#else
182 size_t num_allocated_bytes = new_allocated * sizeof(PyObject *);
183
184 // TODO: For Python3.13 No-GIL this is different code
185 PyObject **items = (PyObject **)NuitkaMem_Realloc(list->ob_item, num_allocated_bytes);
186 if (unlikely(items == NULL)) {
187 PyErr_NoMemory();
188 return false;
189 }
190
191 list->ob_item = items;
192 Py_SET_SIZE(list, new_size);
193 list->allocated = new_allocated;
194#endif
195
196 return true;
197}
198
199bool LIST_EXTEND_FROM_LIST(PyObject *list, PyObject *other) {
200#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
201 PyObject *result = _PyList_Extend((PyListObject *)list, other);
202 if (result != NULL) {
203 Py_DECREF(result);
204 return true;
205 } else {
206 return false;
207 }
208#else
209 assert(PyList_CheckExact(list));
210 assert(PyList_CheckExact(other));
211
212 size_t n = PyList_GET_SIZE(other);
213
214 if (n == 0) {
215 return true;
216 }
217
218 size_t m = Py_SIZE(list);
219
220 if (LIST_RESIZE((PyListObject *)list, m + n) == false) {
221 return false;
222 }
223
224 PyObject **src = &PyList_GET_ITEM(other, 0);
225 PyObject **dest = &PyList_GET_ITEM(list, m);
226
227 for (size_t i = 0; i < n; i++) {
228 PyObject *o = src[i];
229 Py_INCREF(o);
230
231 dest[i] = o;
232 }
233
234 return true;
235#endif
236}
237
238bool LIST_EXTEND_FROM_ITERABLE(PyThreadState *tstate, PyObject *target, PyObject *other) {
239 CHECK_OBJECT(target);
240 assert(PyList_CheckExact(target));
241
242 CHECK_OBJECT(other);
243
244 PyListObject *list = (PyListObject *)target;
245
246#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
247 PyObject *result = _PyList_Extend(list, other);
248 if (result != NULL) {
249 Py_DECREF(result);
250 return true;
251 } else {
252 return false;
253 }
254#else
255 // First attempt those things that occur most often. Keep in mind that
256 // other might be the same object as list.
257 PyObject **src;
258 Py_ssize_t src_size;
259
260 if (PyList_CheckExact(other)) { // this covers list == other too.
261 src = _PyList_ITEMS(other);
262 src_size = PyList_GET_SIZE(other);
263 } else if (PyTuple_CheckExact(other)) {
264 src = _PyTuple_ITEMS(other);
265 src_size = PyTuple_GET_SIZE(other);
266 } else {
267 src = NULL;
268#ifndef __NUITKA_NO_ASSERT__
269 src_size = 0;
270#endif
271 }
272
273 if (src != NULL) {
274 if (src_size == 0) {
275 return true;
276 }
277
278 Py_ssize_t list_size = PyList_GET_SIZE(list);
279
280 // Overflow is not really realistic, so we only assert against it.
281 assert(list_size <= PY_SSIZE_T_MAX - src_size);
282 if (LIST_RESIZE(list, list_size + src_size) == false) {
283 return false;
284 }
285
286 PyObject **target_items = _PyList_ITEMS(list) + list_size;
287
288 for (Py_ssize_t i = 0; i < src_size; i++) {
289 PyObject *value = src[i];
290 Py_INCREF(value);
291 *target_items++ = value;
292 }
293
294 return true;
295 }
296
297 // Slow path needs to use iterator. TODO:
298 PyObject *iter = MAKE_ITERATOR(tstate, other);
299
300 if (iter == NULL) {
301 return false;
302 }
303 PyObject *(*iternext)(PyObject *) = *Py_TYPE(iter)->tp_iternext;
304
305 Py_ssize_t cur_size = PyList_GET_SIZE(list);
306
307#if PYTHON_VERSION >= 0x300
308 // Guess a iterator size if possible
309 src_size = PyObject_LengthHint(other, 8);
310
311 if (src_size < 0) {
312 Py_DECREF(iter);
313 return false;
314 }
315
316 Py_ssize_t list_size = PyList_GET_SIZE(list);
317
318 if (list_size > PY_SSIZE_T_MAX - src_size) {
319 // Overflow is not really realistic, hope is, it will not come true.
320 } else {
321 // Allocate the space in one go.
322 if (LIST_RESIZE(list, list_size + src_size) == false) {
323 Py_DECREF(iter);
324 return false;
325 }
326
327 // Restore validity of the object for the time being.
328 Py_SET_SIZE(list, list_size);
329 }
330#endif
331
332 for (;;) {
333 PyObject *item = iternext(iter);
334
335 if (item == NULL) {
336 bool stop_iteration_error = CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(tstate);
337
338 Py_DECREF(iter);
339
340 if (unlikely(stop_iteration_error == false)) {
341 if (cur_size < list->allocated) {
342 if (LIST_RESIZE(list, cur_size) == false) {
343 return false;
344 }
345 }
346
347 return false;
348 }
349
350 break;
351 }
352
353 CHECK_OBJECT(item);
354
355 if (cur_size < list->allocated) {
356 // Already allocated, so we can just set it.
357 PyList_SET_ITEM(list, cur_size, item);
358 Py_SET_SIZE(list, cur_size + 1);
359 } else {
360 assert(cur_size != PY_SSIZE_T_MAX);
361
362 if (LIST_RESIZE(list, cur_size + 1) == false) {
363 return false;
364 }
365
366 PyList_SET_ITEM(list, cur_size, item);
367 }
368 cur_size += 1;
369 }
370
371 /* Cut back result list if initial guess was too large. */
372 assert(cur_size == PyList_GET_SIZE(list));
373
374 if (cur_size < list->allocated) {
375 if (LIST_RESIZE(list, cur_size) == false) {
376 return false;
377 }
378 }
379
380 return true;
381#endif
382}
383
384#if PYTHON_VERSION >= 0x390
385bool LIST_EXTEND_FOR_UNPACK(PyThreadState *tstate, PyObject *list, PyObject *other) {
386 // TODO: For improved performance, inline this, but we probably wait
387 // until code generation for this kind of helpers is there.
388 bool result = LIST_EXTEND_FROM_ITERABLE(tstate, list, other);
389
390 if (likely(result)) {
391 return true;
392 }
393
394 PyObject *error = GET_ERROR_OCCURRED(tstate);
395
396 assert(error != NULL);
397
398 if (EXCEPTION_MATCH_BOOL_SINGLE(tstate, error, PyExc_TypeError) &&
399 (Py_TYPE(other)->tp_iter == NULL && !PySequence_Check(other))) {
400 CLEAR_ERROR_OCCURRED(tstate);
401 PyErr_Format(PyExc_TypeError, "Value after * must be an iterable, not %s", Py_TYPE(other)->tp_name);
402 }
403
404 return false;
405}
406#endif
407
408bool LIST_APPEND1(PyObject *target, PyObject *item) {
409 CHECK_OBJECT(target);
410 assert(PyList_CheckExact(target));
411
412 CHECK_OBJECT(item);
413
414#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
415 int res = PyList_Append(target, item);
416 Py_DECREF(item);
417 return res == 0;
418#else
419 PyListObject *list = (PyListObject *)target;
420
421 Py_ssize_t cur_size = PyList_GET_SIZE(list);
422
423 // Overflow is not really realistic, so we only assert against it.
424 assert(cur_size <= PY_SSIZE_T_MAX);
425
426 if (LIST_RESIZE(list, cur_size + 1) == false) {
427 return false;
428 }
429
430 PyList_SET_ITEM(list, cur_size, item);
431
432 return true;
433#endif
434}
435
436bool LIST_APPEND0(PyObject *target, PyObject *item) {
437 CHECK_OBJECT(target);
438 assert(PyList_CheckExact(target));
439
440 CHECK_OBJECT(item);
441
442#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
443 int res = PyList_Append(target, item);
444 return res == 0;
445#else
446 PyListObject *list = (PyListObject *)target;
447
448 Py_ssize_t cur_size = PyList_GET_SIZE(list);
449
450 // Overflow is not really realistic, so we only assert against it.
451 assert(cur_size <= PY_SSIZE_T_MAX);
452
453 if (LIST_RESIZE(list, cur_size + 1) == false) {
454 return false;
455 }
456
457 PyList_SET_ITEM0(list, cur_size, item);
458
459 return true;
460#endif
461}
462
463bool LIST_REMOVE(PyObject *target, PyObject *item) {
464 CHECK_OBJECT(target);
465 assert(PyList_CheckExact(target));
466
467 CHECK_OBJECT(item);
468
469#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT && 0
470 // TODO: This is not exposed, would need to delete as slice instead.
471 int res = PyList_Remove(target, item);
472 return res == 0;
473#else
474 PyListObject *list = (PyListObject *)target;
475
476 Py_ssize_t cur_size = PyList_GET_SIZE(list);
477
478 for (Py_ssize_t i = 0; i < cur_size; i++) {
479 PyObject *element = list->ob_item[i];
480
481 Py_INCREF(element);
482 nuitka_bool cmp = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(element, item);
483 Py_DECREF(element);
484
485 if (cmp == NUITKA_BOOL_TRUE) {
486 Py_DECREF(element);
487 Py_SET_SIZE(list, cur_size - 1);
488
489 memmove(list->ob_item + i, list->ob_item + i + 1, sizeof(PyObject *) * (cur_size - i - 1));
490
491 return true;
492 } else if (unlikely(cmp == NUITKA_BOOL_EXCEPTION)) {
493 return false;
494 }
495 }
496
497 PyThreadState *tstate = PyThreadState_GET();
498
499 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ValueError, "list.remove(x): x not in list");
500 return false;
501#endif
502}
503
504void LIST_CLEAR(PyObject *target) {
505 CHECK_OBJECT(target);
506 assert(PyList_CheckExact(target));
507
508 PyListObject *list = (PyListObject *)target;
509
510 PyObject **items = list->ob_item;
511
512 if (items != NULL) {
513 // Make the list empty first, so the data we release is not accessible.
514 Py_ssize_t i = Py_SIZE(list);
515 Py_SET_SIZE(list, 0);
516 list->ob_item = NULL;
517 list->allocated = 0;
518
519 while (--i >= 0) {
520 Py_XDECREF(items[i]);
521 }
522
523 PyMem_Free(items);
524 }
525}
526
527PyObject *getListIndexObject(Py_ssize_t value) {
528#if PYTHON_VERSION < 0x300
529 return PyInt_FromSsize_t(value);
530#else
531 // TODO: Actually to be fully correct, we will need a "Nuitka_LongFromCSsize_t" which
532 // we do not have yet.
533 return Nuitka_LongFromCLong((long)value);
534#endif
535}
536
537PyObject *LIST_COUNT(PyObject *list, PyObject *item) {
538 CHECK_OBJECT(list);
539 assert(PyList_CheckExact(list));
540
541 Py_ssize_t count = 0;
542
543 for (Py_ssize_t i = 0; i < Py_SIZE(list); i++) {
544 PyObject *element = PyList_GET_ITEM(list, i);
545
546 // Fast path, is identical
547 if (element == item) {
548 count++;
549 continue;
550 }
551
552 // Rich compare element while holding a reference. TODO: If we knew the type
553 // of "item" we could be faster by picking variants that know stuff, but
554 // maybe it is not as important.
555 Py_INCREF(element);
556 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(element, item);
557 Py_DECREF(element);
558
559 if (nbool_res == NUITKA_BOOL_TRUE) {
560 count++;
561 continue;
562 }
563
564 // Pass on exceptions from comparisons.
565 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
566 return NULL;
567 }
568 }
569
570 return getListIndexObject(count);
571}
572
573static PyObject *_LIST_INDEX_COMMON(PyThreadState *tstate, PyListObject *list, PyObject *item, Py_ssize_t start,
574 Py_ssize_t stop) {
575 // Negative values for start/stop are handled here.
576 if (start < 0) {
577 start += Py_SIZE(list);
578
579 if (start < 0) {
580 start = 0;
581 }
582 }
583
584 if (stop < 0) {
585 stop += Py_SIZE(list);
586
587 if (stop < 0) {
588 stop = 0;
589 }
590 }
591
592 for (Py_ssize_t i = start; i < stop && i < Py_SIZE(list); i++) {
593 PyObject *element = list->ob_item[i];
594
595 Py_INCREF(element);
596 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(element, item);
597 Py_DECREF(element);
598
599 if (nbool_res == NUITKA_BOOL_TRUE) {
600 return getListIndexObject(i);
601 }
602
603 // Pass on exceptions from comparisons.
604 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
605 return NULL;
606 }
607 }
608
609#if PYTHON_VERSION < 0x300
610 PyObject *err_format = PyString_FromString("%r is not in list");
611 PyObject *format_tuple = MAKE_TUPLE1_0(tstate, item);
612 PyObject *err_string = PyString_Format(err_format, format_tuple);
613 Py_DECREF(format_tuple);
614
615 if (err_string == NULL) {
616 return NULL;
617 }
618
619 SET_CURRENT_EXCEPTION_TYPE0_VALUE1(tstate, PyExc_ValueError, err_string);
620 return NULL;
621#else
622 PyErr_Format(PyExc_ValueError, "%R is not in list", item);
623 return NULL;
624#endif
625}
626
627PyObject *LIST_INDEX2(PyThreadState *tstate, PyObject *list, PyObject *item) {
628 CHECK_OBJECT(list);
629 assert(PyList_CheckExact(list));
630
631 return _LIST_INDEX_COMMON(tstate, (PyListObject *)list, item, 0, Py_SIZE(list));
632}
633
634PyObject *LIST_INDEX3(PyThreadState *tstate, PyObject *list, PyObject *item, PyObject *start) {
635 CHECK_OBJECT(list);
636 assert(PyList_CheckExact(list));
637
638 PyObject *start_index = Nuitka_Number_IndexAsLong(start);
639
640 if (unlikely(start_index == NULL)) {
641 // TODO: Clearing should be useless here.
642 CLEAR_ERROR_OCCURRED(tstate);
643
644 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
645 "slice indices must be integers or have an __index__ method");
646 return NULL;
647 }
648
649 Py_ssize_t start_ssize;
650#if PYTHON_VERSION < 0x300
651 if (PyInt_CheckExact(start_index)) {
652 start_ssize = PyInt_AS_LONG(start_index);
653 } else {
654 start_ssize = PyLong_AsSsize_t(start_index);
655 }
656#else
657 start_ssize = PyLong_AsSsize_t(start_index);
658#endif
659
660 Py_DECREF(start_index);
661
662 return _LIST_INDEX_COMMON(tstate, (PyListObject *)list, item, start_ssize, Py_SIZE(list));
663}
664
665PyObject *LIST_INDEX4(PyThreadState *tstate, PyObject *list, PyObject *item, PyObject *start, PyObject *stop) {
666 CHECK_OBJECT(list);
667 assert(PyList_CheckExact(list));
668
669 PyObject *start_index = Nuitka_Number_IndexAsLong(start);
670
671 if (unlikely(start_index == NULL)) {
672 CLEAR_ERROR_OCCURRED(tstate);
673
674 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
675 "slice indices must be integers or have an __index__ method");
676 return NULL;
677 }
678
679 Py_ssize_t start_ssize;
680#if PYTHON_VERSION < 0x300
681 if (PyInt_CheckExact(start_index)) {
682 start_ssize = PyInt_AS_LONG(start_index);
683 } else {
684 start_ssize = PyLong_AsSsize_t(start_index);
685 }
686#else
687 start_ssize = PyLong_AsSsize_t(start_index);
688#endif
689
690 Py_DECREF(start_index);
691
692 PyObject *stop_index = Nuitka_Number_IndexAsLong(stop);
693
694 if (unlikely(stop_index == NULL)) {
695 Py_DECREF(start_index);
696
697 CLEAR_ERROR_OCCURRED(tstate);
698
699 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
700 "slice indices must be integers or have an __index__ method");
701 return NULL;
702 }
703
704 Py_ssize_t stop_ssize;
705#if PYTHON_VERSION < 0x300
706 if (PyInt_CheckExact(stop_index)) {
707 stop_ssize = PyInt_AS_LONG(stop_index);
708 } else {
709 stop_ssize = PyLong_AsSsize_t(stop_index);
710 }
711#else
712 stop_ssize = PyLong_AsSsize_t(stop_index);
713#endif
714
715 Py_DECREF(stop_index);
716
717 return _LIST_INDEX_COMMON(tstate, (PyListObject *)list, item, start_ssize, stop_ssize);
718}
719
720bool LIST_INSERT(PyThreadState *tstate, PyObject *list, PyObject *index, PyObject *item) {
721 CHECK_OBJECT(list);
722 assert(PyList_CheckExact(list));
723 CHECK_OBJECT(index);
724 CHECK_OBJECT(item);
725
726 // TODO: Avoid the clear, by having this as a variant that doesn't set the
727 // exception to begin with
728 PyObject *index_long = Nuitka_Number_IndexAsLong(index);
729
730 if (unlikely(index_long == NULL)) {
731 CLEAR_ERROR_OCCURRED(tstate);
732
733 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' cannot be interpreted as an integer", index);
734 return false;
735 }
736
737 Py_ssize_t index_ssize;
738#if PYTHON_VERSION < 0x300
739 if (PyInt_CheckExact(index_long)) {
740 index_ssize = PyInt_AS_LONG(index_long);
741 } else {
742 index_ssize = PyLong_AsSsize_t(index_long);
743 }
744#else
745 index_ssize = PyLong_AsSsize_t(index_long);
746#endif
747
748 Py_DECREF(index_long);
749
750 LIST_INSERT_CONST(list, index_ssize, item);
751 return true;
752}
753
754void LIST_INSERT_CONST(PyObject *list, Py_ssize_t index, PyObject *item) {
755 CHECK_OBJECT(list);
756 assert(PyList_CheckExact(list));
757 CHECK_OBJECT(item);
758
759 PyListObject *list_object = (PyListObject *)list;
760
761 Py_ssize_t n = Py_SIZE(list_object);
762
763 // Expand the list by needed space.
764 if (LIST_RESIZE(list_object, n + 1) == false) {
765 abort();
766 }
767
768 // Negative values and overflow for for index are handled here.
769 if (index < 0) {
770 index += n;
771 if (index < 0) {
772 index = 0;
773 }
774 }
775 if (index > n) {
776 index = n;
777 }
778
779 // Shift the items behind the insert index.
780 PyObject **items = list_object->ob_item;
781
782 for (Py_ssize_t i = n; --i >= index;) {
783 items[i + 1] = items[i];
784 }
785
786 Py_INCREF(item);
787 items[index] = item;
788}
789
790static void _Nuitka_ReverseObjectsSlice(PyObject **lo, PyObject **hi) {
791 assert(lo != NULL && hi != NULL);
792
793 hi -= 1;
794
795 while (lo < hi) {
796 {
797 PyObject *t = *lo;
798 *lo = *hi;
799 *hi = t;
800 }
801
802 lo += 1;
803 hi -= 1;
804 }
805}
806
807void LIST_REVERSE(PyObject *list) {
808 CHECK_OBJECT(list);
809 assert(PyList_CheckExact(list));
810
811 PyListObject *list_object = (PyListObject *)list;
812
813 if (Py_SIZE(list_object) > 1) {
814 _Nuitka_ReverseObjectsSlice(list_object->ob_item, list_object->ob_item + Py_SIZE(list_object));
815 }
816}
817
818#if PYTHON_VERSION >= 0x300 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT)
819static bool allocateListItems(PyListObject *list, Py_ssize_t size) {
820 PyObject **items = PyMem_New(PyObject *, size);
821
822 if (unlikely(items == NULL)) {
823 PyErr_NoMemory();
824 return false;
825 }
826
827 list->ob_item = items;
828 list->allocated = size;
829
830 return true;
831}
832
833#endif
834
835PyObject *MAKE_LIST(PyThreadState *tstate, PyObject *iterable) {
836 // Can leave the size hinting to later functions, because the list is allocated empty without
837 // items, and when then extending, etc. length hints can be used.
838 PyObject *list = MAKE_LIST_EMPTY(tstate, 0);
839
840#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
841 PyObject *result = _PyList_Extend((PyListObject *)list, iterable);
842 if (result == NULL) {
843 Py_DECREF(list);
844 return NULL;
845 } else {
846 Py_DECREF(result);
847 return list;
848 }
849#else
850 Py_INCREF(iterable);
851
852#if PYTHON_VERSION >= 0x300
853 if (Nuitka_PyObject_HasLen(iterable)) {
854 Py_ssize_t iter_len = Nuitka_PyObject_Size(iterable);
855
856 if (unlikely(iter_len == -1)) {
857 if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
858 return NULL;
859 }
860
861 CLEAR_ERROR_OCCURRED(tstate);
862 }
863
864 if (iter_len > 0) {
865 if (allocateListItems((PyListObject *)list, iter_len) == false) {
866 return NULL;
867 }
868 }
869 }
870#endif
871
872 bool res = LIST_EXTEND_FROM_ITERABLE(tstate, list, iterable);
873
874 Py_DECREF(iterable);
875
876 if (unlikely(res == false)) {
877 Py_DECREF(list);
878 return NULL;
879 }
880
881 return list;
882#endif
883}
884
885#include "HelpersListsGenerated.c"
886// Part of "Nuitka", an optimizing Python compiler that is compatible and
887// integrates with CPython, but also works on its own.
888//
889// Licensed under the Apache License, Version 2.0 (the "License");
890// you may not use this file except in compliance with the License.
891// You may obtain a copy of the License at
892//
893// http://www.apache.org/licenses/LICENSE-2.0
894//
895// Unless required by applicable law or agreed to in writing, software
896// distributed under the License is distributed on an "AS IS" BASIS,
897// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
898// See the License for the specific language governing permissions and
899// limitations under the License.