Nuitka
The Python compiler
Loading...
Searching...
No Matches
slices.h
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3#ifndef __NUITKA_HELPER_SLICES_H__
4#define __NUITKA_HELPER_SLICES_H__
5
6/* This file is included from another C file, help IDEs to still parse it on its own. */
7#ifdef __IDE_ONLY__
8#include "nuitka/prelude.h"
9#endif
10
11#if PYTHON_VERSION >= 0x3a0
12extern PyObject *Nuitka_Slice_New(PyThreadState *tstate, PyObject *start, PyObject *stop, PyObject *step);
13#else
14#define Nuitka_Slice_New(tstate, start, stop, step) PySlice_New(start, stop, step)
15#endif
16
17// Note: Cannot these cannot fail, PySlice_New does not return errors.
18NUITKA_MAY_BE_UNUSED static PyObject *MAKE_SLICE_OBJECT3(PyThreadState *tstate, PyObject *start, PyObject *stop,
19 PyObject *step) {
20 CHECK_OBJECT(start);
21 CHECK_OBJECT(stop);
22 CHECK_OBJECT(step);
23
24 return Nuitka_Slice_New(tstate, start, stop, step);
25}
26NUITKA_MAY_BE_UNUSED static PyObject *MAKE_SLICE_OBJECT2(PyThreadState *tstate, PyObject *start, PyObject *stop) {
27 CHECK_OBJECT(start);
28 CHECK_OBJECT(stop);
29
30 return Nuitka_Slice_New(tstate, start, stop, Py_None);
31}
32NUITKA_MAY_BE_UNUSED static PyObject *MAKE_SLICE_OBJECT1(PyThreadState *tstate, PyObject *stop) {
33 CHECK_OBJECT(stop);
34
35 return Nuitka_Slice_New(tstate, Py_None, stop, Py_None);
36}
37
38#if PYTHON_VERSION < 0x300
39// Note: It appears that Python3 has no index slicing operations anymore, but
40// uses slice objects all the time. That's fine and make sure we adhere to it by
41// guarding the presence of the helpers.
42
43static inline bool IS_INDEXABLE(PyObject *value) {
44 return value == Py_None ||
45#if PYTHON_VERSION < 0x300
46 PyInt_Check(value) ||
47#endif
48 PyLong_Check(value) || Nuitka_Index_Check(value);
49}
50
51static Py_ssize_t CONVERT_TO_INDEX(PyThreadState *tstate, PyObject *value) {
52 CHECK_OBJECT(value);
53
54 if (PyInt_Check(value)) {
55 return PyInt_AS_LONG(value);
56 } else if (Nuitka_Index_Check(value)) {
57 return PyNumber_AsSsize_t(value, NULL);
58 } else {
59 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
60 "slice indices must be integers or None or have an __index__ method");
61 return -1;
62 }
63}
64
65NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_SLICE(PyThreadState *tstate, PyObject *source, PyObject *lower,
66 PyObject *upper) {
67 CHECK_OBJECT(source);
68 CHECK_OBJECT(lower);
69 CHECK_OBJECT(upper);
70
71 PySequenceMethods *tp_as_sequence = Py_TYPE(source)->tp_as_sequence;
72
73 if (tp_as_sequence && tp_as_sequence->sq_slice && IS_INDEXABLE(lower) && IS_INDEXABLE(upper)) {
74 Py_ssize_t ilow = 0;
75
76 if (lower != Py_None) {
77 ilow = CONVERT_TO_INDEX(tstate, lower);
78
79 if (ilow == -1 && HAS_ERROR_OCCURRED(tstate)) {
80 return NULL;
81 }
82 }
83
84 Py_ssize_t ihigh = PY_SSIZE_T_MAX;
85
86 if (upper != Py_None) {
87 ihigh = CONVERT_TO_INDEX(tstate, upper);
88
89 if (ihigh == -1 && HAS_ERROR_OCCURRED(tstate)) {
90 return NULL;
91 }
92 }
93
94 PyObject *result = PySequence_GetSlice(source, ilow, ihigh);
95
96 if (unlikely(result == NULL)) {
97 return NULL;
98 }
99
100 return result;
101 } else {
102 PyObject *slice = PySlice_New(lower, upper, NULL);
103
104 if (unlikely(slice == NULL)) {
105 return NULL;
106 }
107
108 PyObject *result = PyObject_GetItem(source, slice);
109 Py_DECREF(slice);
110
111 if (unlikely(result == NULL)) {
112 return NULL;
113 }
114
115 return result;
116 }
117}
118
119NUITKA_MAY_BE_UNUSED static PyObject *LOOKUP_INDEX_SLICE(PyObject *source, Py_ssize_t lower, Py_ssize_t upper) {
120 CHECK_OBJECT(source);
121
122 PyObject *result = PySequence_GetSlice(source, lower, upper);
123
124 if (unlikely(result == NULL)) {
125 return NULL;
126 }
127
128 return result;
129}
130
131NUITKA_MAY_BE_UNUSED static bool SET_SLICE(PyThreadState *tstate, PyObject *target, PyObject *lower, PyObject *upper,
132 PyObject *value) {
133 CHECK_OBJECT(target);
134 CHECK_OBJECT(lower);
135 CHECK_OBJECT(upper);
136 CHECK_OBJECT(value);
137
138 PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence;
139
140 if (tp_as_sequence && tp_as_sequence->sq_ass_slice && IS_INDEXABLE(lower) && IS_INDEXABLE(upper)) {
141 Py_ssize_t lower_int = 0;
142
143 if (lower != Py_None) {
144 lower_int = CONVERT_TO_INDEX(tstate, lower);
145
146 if (lower_int == -1 && HAS_ERROR_OCCURRED(tstate)) {
147 return false;
148 }
149 }
150
151 Py_ssize_t upper_int = PY_SSIZE_T_MAX;
152
153 if (upper != Py_None) {
154 upper_int = CONVERT_TO_INDEX(tstate, upper);
155
156 if (upper_int == -1 && HAS_ERROR_OCCURRED(tstate)) {
157 return false;
158 }
159 }
160
161 int status = PySequence_SetSlice(target, lower_int, upper_int, value);
162
163 if (unlikely(status == -1)) {
164 return false;
165 }
166 } else {
167 PyObject *slice = PySlice_New(lower, upper, NULL);
168
169 if (unlikely(slice == NULL)) {
170 return false;
171 }
172
173 int status = PyObject_SetItem(target, slice, value);
174 Py_DECREF(slice);
175
176 if (unlikely(status == -1)) {
177 return false;
178 }
179 }
180
181 return true;
182}
183
184NUITKA_MAY_BE_UNUSED static bool SET_INDEX_SLICE(PyObject *target, Py_ssize_t lower, Py_ssize_t upper,
185 PyObject *value) {
186 CHECK_OBJECT(target);
187 CHECK_OBJECT(value);
188
189 PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence;
190
191 if (tp_as_sequence && tp_as_sequence->sq_ass_slice) {
192 int status = PySequence_SetSlice(target, lower, upper, value);
193
194 if (unlikely(status == -1)) {
195 return false;
196 }
197 } else {
198 PyObject *slice = _PySlice_FromIndices(lower, upper);
199
200 if (unlikely(slice == NULL)) {
201 return false;
202 }
203
204 int status = PyObject_SetItem(target, slice, value);
205
206 Py_DECREF(slice);
207
208 if (unlikely(status == -1)) {
209 return false;
210 }
211 }
212
213 return true;
214}
215
216NUITKA_MAY_BE_UNUSED static bool DEL_SLICE(PyThreadState *tstate, PyObject *target, PyObject *lower, PyObject *upper) {
217 CHECK_OBJECT(target);
218 CHECK_OBJECT(lower);
219 CHECK_OBJECT(upper);
220
221 PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence;
222
223 if (tp_as_sequence && tp_as_sequence->sq_ass_slice && IS_INDEXABLE(lower) && IS_INDEXABLE(upper)) {
224 Py_ssize_t lower_int = 0;
225
226 if (lower != Py_None) {
227 lower_int = CONVERT_TO_INDEX(tstate, lower);
228
229 if (lower_int == -1 && HAS_ERROR_OCCURRED(tstate)) {
230 return false;
231 }
232 }
233
234 Py_ssize_t upper_int = PY_SSIZE_T_MAX;
235
236 if (upper != Py_None) {
237 upper_int = CONVERT_TO_INDEX(tstate, upper);
238
239 if (upper_int == -1 && HAS_ERROR_OCCURRED(tstate)) {
240 return false;
241 }
242 }
243
244 int status = PySequence_DelSlice(target, lower_int, upper_int);
245
246 if (unlikely(status == -1)) {
247 return false;
248 }
249 } else {
250 PyObject *slice = PySlice_New(lower, upper, NULL);
251
252 if (unlikely(slice == NULL)) {
253 return false;
254 }
255
256 int status = PyObject_DelItem(target, slice);
257 Py_DECREF(slice);
258
259 if (unlikely(status == -1)) {
260 return false;
261 }
262 }
263
264 return true;
265}
266
267NUITKA_MAY_BE_UNUSED static bool DEL_INDEX_SLICE(PyObject *target, Py_ssize_t lower, Py_ssize_t upper) {
268 CHECK_OBJECT(target);
269
270 PySequenceMethods *tp_as_sequence = Py_TYPE(target)->tp_as_sequence;
271
272 if (tp_as_sequence && tp_as_sequence->sq_ass_slice) {
273 int status = PySequence_DelSlice(target, lower, upper);
274
275 if (unlikely(status == -1)) {
276 return false;
277 }
278 } else {
279 PyObject *slice = _PySlice_FromIndices(lower, upper);
280
281 if (unlikely(slice == NULL)) {
282 return false;
283 }
284
285 int status = PyObject_DelItem(target, slice);
286
287 Py_DECREF(slice);
288
289 if (unlikely(status == -1)) {
290 return false;
291 }
292 }
293
294 return true;
295}
296
297#endif
298
299#endif
300
301// Part of "Nuitka", an optimizing Python compiler that is compatible and
302// integrates with CPython, but also works on its own.
303//
304// Licensed under the Apache License, Version 2.0 (the "License");
305// you may not use this file except in compliance with the License.
306// You may obtain a copy of the License at
307//
308// http://www.apache.org/licenses/LICENSE-2.0
309//
310// Unless required by applicable law or agreed to in writing, software
311// distributed under the License is distributed on an "AS IS" BASIS,
312// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
313// See the License for the specific language governing permissions and
314// limitations under the License.