this repo has no description
at trunk 178 lines 6.1 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2// tupleobject.c implementation 3 4#include <cstdarg> 5 6#include "api-handle.h" 7#include "objects.h" 8#include "runtime.h" 9#include "tuple-builtins.h" 10 11namespace py { 12 13PY_EXPORT PyTypeObject* PyTupleIter_Type_Ptr() { 14 Runtime* runtime = Thread::current()->runtime(); 15 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 16 runtime, runtime->typeAt(LayoutId::kTupleIterator))); 17} 18 19PY_EXPORT PyObject* PyTuple_New(Py_ssize_t length) { 20 Runtime* runtime = Thread::current()->runtime(); 21 if (length == 0) { 22 return ApiHandle::newReferenceWithManaged(runtime, runtime->emptyTuple()); 23 } 24 RawMutableTuple tuple = MutableTuple::cast(runtime->newMutableTuple(length)); 25 tuple.fill(NoneType::object()); 26 return ApiHandle::newReferenceWithManaged(runtime, tuple.becomeImmutable()); 27} 28 29PY_EXPORT int PyTuple_CheckExact_Func(PyObject* obj) { 30 return ApiHandle::asObject(ApiHandle::fromPyObject(obj)).isTuple(); 31} 32 33PY_EXPORT int PyTuple_Check_Func(PyObject* obj) { 34 return Thread::current()->runtime()->isInstanceOfTuple( 35 ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 36} 37 38PY_EXPORT PyObject* PyTuple_GET_ITEM_Func(PyObject* pytuple, Py_ssize_t pos) { 39 Runtime* runtime = Thread::current()->runtime(); 40 RawObject obj = ApiHandle::asObjectNoImmediate(ApiHandle::fromPyObject(pytuple)); 41 DCHECK(runtime->isInstanceOfTuple(obj), 42 "non-tuple argument to PyTuple_GET_ITEM"); 43 RawTuple tuple = tupleUnderlying(obj); 44 DCHECK_INDEX(pos, tuple.length()); 45 return ApiHandle::borrowedReference(runtime, tuple.at(pos)); 46} 47 48PY_EXPORT Py_ssize_t PyTuple_GET_SIZE_Func(PyObject* pytuple) { 49 RawObject obj = ApiHandle::asObjectNoImmediate(ApiHandle::fromPyObject(pytuple)); 50 DCHECK(Thread::current()->runtime()->isInstanceOfTuple(obj), 51 "non-tuple argument to PyTuple_GET_SIZE"); 52 return tupleUnderlying(obj).length(); 53} 54 55PY_EXPORT PyObject* PyTuple_GetItem(PyObject* pytuple, Py_ssize_t pos) { 56 Thread* thread = Thread::current(); 57 Runtime* runtime = thread->runtime(); 58 RawObject obj = ApiHandle::asObject(ApiHandle::fromPyObject(pytuple)); 59 if (!runtime->isInstanceOfTuple(obj)) { 60 thread->raiseBadInternalCall(); 61 return nullptr; 62 } 63 64 RawTuple tuple = tupleUnderlying(obj); 65 if (pos < 0 || pos >= tuple.length()) { 66 thread->raiseWithFmt(LayoutId::kIndexError, "tuple index out of range"); 67 return nullptr; 68 } 69 70 return ApiHandle::borrowedReference(runtime, tuple.at(pos)); 71} 72 73PY_EXPORT PyObject* PyTuple_SET_ITEM_Func(PyObject* pytuple, Py_ssize_t pos, 74 PyObject* pyitem) { 75 RawObject obj = ApiHandle::asObjectNoImmediate(ApiHandle::fromPyObject(pytuple)); 76 RawObject item = pyitem == nullptr ? NoneType::object() 77 : ApiHandle::stealReference(pyitem); 78 DCHECK(Thread::current()->runtime()->isInstanceOfTuple(obj), 79 "non-tuple argument to PyTuple_SET_ITEM"); 80 RawTuple tuple = tupleUnderlying(obj); 81 DCHECK_INDEX(pos, tuple.length()); 82 tuple.atPut(pos, item); 83 return pyitem; 84} 85 86PY_EXPORT int PyTuple_SetItem(PyObject* pytuple, Py_ssize_t pos, 87 PyObject* pyitem) { 88 Thread* thread = Thread::current(); 89 Runtime* runtime = thread->runtime(); 90 RawObject obj = ApiHandle::asObject(ApiHandle::fromPyObject(pytuple)); 91 RawObject item = pyitem == nullptr ? NoneType::object() 92 : ApiHandle::stealReference(pyitem); 93 if (!runtime->isInstanceOfTuple(obj)) { 94 thread->raiseBadInternalCall(); 95 return -1; 96 } 97 98 RawTuple tuple = tupleUnderlying(obj); 99 if (pos < 0 || pos >= tuple.length()) { 100 thread->raiseWithFmt(LayoutId::kIndexError, 101 "tuple assignment index out of range"); 102 return -1; 103 } 104 105 tuple.atPut(pos, item); 106 return 0; 107} 108 109PY_EXPORT Py_ssize_t PyTuple_Size(PyObject* pytuple) { 110 Thread* thread = Thread::current(); 111 Runtime* runtime = thread->runtime(); 112 RawObject obj = ApiHandle::asObject(ApiHandle::fromPyObject(pytuple)); 113 if (!runtime->isInstanceOfTuple(obj)) { 114 thread->raiseBadInternalCall(); 115 return -1; 116 } 117 return tupleUnderlying(obj).length(); 118} 119 120PY_EXPORT PyTypeObject* PyTuple_Type_Ptr() { 121 Runtime* runtime = Thread::current()->runtime(); 122 return reinterpret_cast<PyTypeObject*>( 123 ApiHandle::borrowedReference(runtime, runtime->typeAt(LayoutId::kTuple))); 124} 125 126PY_EXPORT PyObject* PyTuple_Pack(Py_ssize_t n, ...) { 127 Thread* thread = Thread::current(); 128 Runtime* runtime = thread->runtime(); 129 if (n == 0) { 130 return ApiHandle::newReferenceWithManaged(runtime, runtime->emptyTuple()); 131 } 132 133 HandleScope scope(thread); 134 va_list vargs; 135 va_start(vargs, n); 136 MutableTuple tuple(&scope, runtime->newMutableTuple(n)); 137 for (Py_ssize_t i = 0; i < n; i++) { 138 PyObject* item = va_arg(vargs, PyObject*); 139 tuple.atPut(i, ApiHandle::asObject(ApiHandle::fromPyObject(item))); 140 } 141 va_end(vargs); 142 return ApiHandle::newReferenceWithManaged(runtime, tuple.becomeImmutable()); 143} 144 145PY_EXPORT PyObject* PyTuple_GetSlice(PyObject* pytuple, Py_ssize_t low, 146 Py_ssize_t high) { 147 Thread* thread = Thread::current(); 148 if (pytuple == nullptr) { 149 thread->raiseBadInternalCall(); 150 return nullptr; 151 } 152 Runtime* runtime = thread->runtime(); 153 HandleScope scope(thread); 154 Object tuple_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pytuple))); 155 if (!runtime->isInstanceOfTuple(*tuple_obj)) { 156 thread->raiseBadInternalCall(); 157 return nullptr; 158 } 159 Tuple tuple(&scope, tupleUnderlying(*tuple_obj)); 160 word len = tuple.length(); 161 if (low < 0) { 162 low = 0; 163 } else if (low > len) { 164 low = len; 165 } 166 if (high < low) { 167 high = low; 168 } else if (high > len) { 169 high = len; 170 } 171 if (low == 0 && high == len && tuple_obj.isTuple()) { 172 return ApiHandle::newReferenceWithManaged(runtime, *tuple); 173 } 174 return ApiHandle::newReferenceWithManaged( 175 runtime, runtime->tupleSubseq(thread, tuple, low, high - low)); 176} 177 178} // namespace py