this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2// listobject.c implementation
3
4#include "cpython-func.h"
5
6#include "api-handle.h"
7#include "handles.h"
8#include "list-builtins.h"
9#include "objects.h"
10#include "runtime.h"
11
12namespace py {
13
14PY_EXPORT PyTypeObject* PyListIter_Type_Ptr() {
15 Runtime* runtime = Thread::current()->runtime();
16 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference(
17 runtime, runtime->typeAt(LayoutId::kListIterator)));
18}
19
20PY_EXPORT PyObject* PyList_New(Py_ssize_t size) {
21 Thread* thread = Thread::current();
22 if (size < 0) {
23 thread->raiseBadInternalCall();
24 return nullptr;
25 }
26
27 Runtime* runtime = thread->runtime();
28 if (size == 0) {
29 return ApiHandle::newReferenceWithManaged(runtime, runtime->newList());
30 }
31
32 HandleScope scope(thread);
33 List list(&scope, runtime->newList());
34 list.setItems(runtime->newMutableTuple(size));
35 list.setNumItems(size);
36 return ApiHandle::newReferenceWithManaged(runtime, *list);
37}
38
39PY_EXPORT PyTypeObject* PyList_Type_Ptr() {
40 Runtime* runtime = Thread::current()->runtime();
41 return reinterpret_cast<PyTypeObject*>(
42 ApiHandle::borrowedReference(runtime, runtime->typeAt(LayoutId::kList)));
43}
44
45PY_EXPORT int PyList_CheckExact_Func(PyObject* obj) {
46 return ApiHandle::asObject(ApiHandle::fromPyObject(obj)).isList();
47}
48
49PY_EXPORT int PyList_Check_Func(PyObject* obj) {
50 return Thread::current()->runtime()->isInstanceOfList(
51 ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
52}
53
54PY_EXPORT PyObject* PyList_AsTuple(PyObject* pylist) {
55 Thread* thread = Thread::current();
56 Runtime* runtime = thread->runtime();
57 HandleScope scope(thread);
58 if (pylist == nullptr) {
59 thread->raiseBadInternalCall();
60 return nullptr;
61 }
62 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
63 if (!runtime->isInstanceOfList(*list_obj)) {
64 thread->raiseBadInternalCall();
65 return nullptr;
66 }
67 List list(&scope, *list_obj);
68 word length = list.numItems();
69 if (length == 0) {
70 return ApiHandle::newReferenceWithManaged(runtime, runtime->emptyTuple());
71 }
72 MutableTuple result(&scope, runtime->newMutableTuple(length));
73 result.replaceFromWith(0, Tuple::cast(list.items()), length);
74 return ApiHandle::newReferenceWithManaged(runtime, result.becomeImmutable());
75}
76
77PY_EXPORT PyObject* PyList_GetItem(PyObject* pylist, Py_ssize_t i) {
78 Thread* thread = Thread::current();
79 Runtime* runtime = thread->runtime();
80 HandleScope scope(thread);
81 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
82 if (!runtime->isInstanceOfList(*list_obj)) {
83 thread->raiseBadInternalCall();
84 return nullptr;
85 }
86 List list(&scope, *list_obj);
87 if (i >= list.numItems()) {
88 thread->raiseWithFmt(LayoutId::kIndexError,
89 "index out of bounds in PyList_GetItem");
90 return nullptr;
91 }
92 return ApiHandle::borrowedReference(runtime, list.at(i));
93}
94
95PY_EXPORT int PyList_Reverse(PyObject* pylist) {
96 Thread* thread = Thread::current();
97 if (pylist == nullptr) {
98 thread->raiseBadInternalCall();
99 return -1;
100 }
101 Runtime* runtime = thread->runtime();
102 HandleScope scope(thread);
103 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
104 if (!runtime->isInstanceOfList(*list_obj)) {
105 thread->raiseBadInternalCall();
106 return -1;
107 }
108 List list(&scope, *list_obj);
109 listReverse(thread, list);
110 return 0;
111}
112
113PY_EXPORT int PyList_SET_ITEM_Func(PyObject* pylist, Py_ssize_t i,
114 PyObject* item) {
115 Thread* thread = Thread::current();
116 Runtime* runtime = thread->runtime();
117 HandleScope scope(thread);
118 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
119 DCHECK(runtime->isInstanceOfList(*list_obj), "pylist must be a list");
120 List list(&scope, *list_obj);
121 DCHECK_INDEX(i, list.numItems());
122 list.atPut(i, item == nullptr ? NoneType::object()
123 : ApiHandle::stealReference(item));
124 return 0;
125}
126
127PY_EXPORT int PyList_SetItem(PyObject* pylist, Py_ssize_t i, PyObject* item) {
128 Thread* thread = Thread::current();
129 Runtime* runtime = thread->runtime();
130 HandleScope scope(thread);
131 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
132 Object newitem(&scope, item == nullptr ? NoneType::object()
133 : ApiHandle::stealReference(item));
134 if (!runtime->isInstanceOfList(*list_obj)) {
135 thread->raiseBadInternalCall();
136 return -1;
137 }
138 List list(&scope, *list_obj);
139 if (i >= list.numItems()) {
140 thread->raiseWithFmt(LayoutId::kIndexError,
141 "index out of bounds in PyList_SetItem");
142 return -1;
143 }
144 list.atPut(i, *newitem);
145 return 0;
146}
147
148PY_EXPORT int PyList_Append(PyObject* op, PyObject* newitem) {
149 Thread* thread = Thread::current();
150 Runtime* runtime = thread->runtime();
151 HandleScope scope(thread);
152
153 if (newitem == nullptr) {
154 thread->raiseBadInternalCall();
155 return -1;
156 }
157 Object value(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(newitem)));
158
159 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(op)));
160 if (!runtime->isInstanceOfList(*list_obj)) {
161 thread->raiseBadInternalCall();
162 return -1;
163 }
164 List list(&scope, *list_obj);
165
166 runtime->listAdd(thread, list, value);
167 return 0;
168}
169
170PY_EXPORT PyObject* PyList_GetSlice(PyObject* pylist, Py_ssize_t low,
171 Py_ssize_t high) {
172 Thread* thread = Thread::current();
173 Runtime* runtime = thread->runtime();
174 HandleScope scope(thread);
175 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
176 if (!runtime->isInstanceOfList(*list_obj)) {
177 thread->raiseBadInternalCall();
178 return nullptr;
179 }
180 List list(&scope, *list_obj);
181 word length = list.numItems();
182 if (low < 0) {
183 low = 0;
184 } else if (low > length) {
185 low = length;
186 }
187 if (high < low) {
188 high = low;
189 } else if (high > length) {
190 high = length;
191 }
192 return ApiHandle::newReferenceWithManaged(
193 runtime, listSlice(thread, list, low, high, 1));
194}
195
196PY_EXPORT int PyList_Insert(PyObject* pylist, Py_ssize_t where,
197 PyObject* item) {
198 Thread* thread = Thread::current();
199 Runtime* runtime = thread->runtime();
200 HandleScope scope(thread);
201 if (item == nullptr) {
202 thread->raiseBadInternalCall();
203 return -1;
204 }
205 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
206 if (!runtime->isInstanceOfList(*list_obj)) {
207 thread->raiseBadInternalCall();
208 return -1;
209 }
210 List list(&scope, *list_obj);
211 if (list.numItems() == kMaxWord) {
212 thread->raiseWithFmt(LayoutId::kSystemError,
213 "cannot add more objects to list");
214 return -1;
215 }
216 Object item_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(item)));
217 listInsert(thread, list, item_obj, where);
218 return 0;
219}
220
221PY_EXPORT int PyList_SetSlice(PyObject* list, Py_ssize_t low, Py_ssize_t high,
222 PyObject* items) {
223 Thread* thread = Thread::current();
224 Runtime* runtime = thread->runtime();
225 HandleScope scope(thread);
226 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(list)));
227 if (!runtime->isInstanceOfList(*list_obj)) {
228 thread->raiseBadInternalCall();
229 return -1;
230 }
231
232 List self(&scope, *list_obj);
233 word length = self.numItems();
234 if (low < 0) {
235 low = 0;
236 } else if (low > length) {
237 low = length;
238 }
239 if (high < low) {
240 high = low;
241 } else if (high > length) {
242 high = length;
243 }
244
245 Object start(&scope, SmallInt::fromWord(low));
246 Object stop(&scope, SmallInt::fromWord(high));
247 Object step(&scope, NoneType::object());
248 Slice slice(&scope, runtime->newSlice(start, stop, step));
249 Object result(&scope, NoneType::object());
250 if (items == nullptr) {
251 // Equivalent to deleting slice
252 result = thread->invokeMethodStatic2(LayoutId::kList, ID(__delitem__),
253 list_obj, slice);
254 } else {
255 Object items_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(items)));
256 result = thread->invokeMethodStatic3(LayoutId::kList, ID(__setitem__),
257 list_obj, slice, items_obj);
258 }
259 return result.isError() ? -1 : 0;
260}
261
262PY_EXPORT Py_ssize_t PyList_Size(PyObject* p) {
263 Thread* thread = Thread::current();
264 Runtime* runtime = thread->runtime();
265 HandleScope scope(thread);
266
267 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(p)));
268 if (!runtime->isInstanceOfList(*list_obj)) {
269 thread->raiseBadInternalCall();
270 return -1;
271 }
272
273 List list(&scope, *list_obj);
274 return list.numItems();
275}
276
277PY_EXPORT int PyList_Sort(PyObject* pylist) {
278 Thread* thread = Thread::current();
279 if (pylist == nullptr) {
280 thread->raiseBadInternalCall();
281 return -1;
282 }
283 HandleScope scope(thread);
284 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist)));
285 Runtime* runtime = thread->runtime();
286 if (!runtime->isInstanceOfList(*list_obj)) {
287 thread->raiseBadInternalCall();
288 return -1;
289 }
290 List list(&scope, *list_obj);
291 if (listSort(thread, list).isError()) {
292 return -1;
293 }
294 return 0;
295}
296
297} // namespace py