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