this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "cpython-func.h"
3
4#include "api-handle.h"
5#include "runtime.h"
6#include "set-builtins.h"
7
8namespace py {
9
10PY_EXPORT int PyAnySet_Check_Func(PyObject* arg) {
11 DCHECK(arg != nullptr, "obj must not be nullptr");
12 Thread* thread = Thread::current();
13 Runtime* runtime = thread->runtime();
14 RawObject obj = ApiHandle::asObject(ApiHandle::fromPyObject(arg));
15 return runtime->isInstanceOfSet(obj) || runtime->isInstanceOfFrozenSet(obj);
16}
17
18PY_EXPORT int PyAnySet_CheckExact_Func(PyObject* arg) {
19 DCHECK(arg != nullptr, "obj must not be nullptr");
20 RawObject obj = ApiHandle::asObject(ApiHandle::fromPyObject(arg));
21 return obj.isSet() || obj.isFrozenSet();
22}
23
24PY_EXPORT int PyFrozenSet_Check_Func(PyObject* obj) {
25 DCHECK(obj != nullptr, "obj must not be nullptr");
26 return Thread::current()->runtime()->isInstanceOfFrozenSet(
27 ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
28}
29
30PY_EXPORT int PyFrozenSet_CheckExact_Func(PyObject* obj) {
31 DCHECK(obj != nullptr, "obj must not be nullptr");
32 return ApiHandle::asObject(ApiHandle::fromPyObject(obj)).isFrozenSet();
33}
34
35PY_EXPORT PyObject* PyFrozenSet_New(PyObject* iterable) {
36 Thread* thread = Thread::current();
37 Runtime* runtime = thread->runtime();
38 if (iterable == nullptr) {
39 return ApiHandle::newReferenceWithManaged(runtime,
40 runtime->emptyFrozenSet());
41 }
42 HandleScope scope(thread);
43 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(iterable)));
44 FrozenSet set(&scope, runtime->newFrozenSet());
45 Object result(&scope, setUpdate(thread, set, obj));
46 if (result.isError()) {
47 return nullptr;
48 }
49 return ApiHandle::newReferenceWithManaged(runtime, *set);
50}
51
52PY_EXPORT PyTypeObject* PyFrozenSet_Type_Ptr() {
53 Runtime* runtime = Thread::current()->runtime();
54 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference(
55 runtime, runtime->typeAt(LayoutId::kFrozenSet)));
56}
57
58PY_EXPORT PyTypeObject* PySetIter_Type_Ptr() {
59 Runtime* runtime = Thread::current()->runtime();
60 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference(
61 runtime, runtime->typeAt(LayoutId::kSetIterator)));
62}
63
64PY_EXPORT int PySet_Add(PyObject* anyset, PyObject* key) {
65 Thread* thread = Thread::current();
66 Runtime* runtime = thread->runtime();
67 HandleScope scope(thread);
68
69 Object set_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(anyset)));
70
71 // TODO(T28454727): add FrozenSet
72 if (!runtime->isInstanceOfSet(*set_obj)) {
73 thread->raiseBadInternalCall();
74 return -1;
75 }
76
77 Set set(&scope, *set_obj);
78 Object key_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(key)));
79 Object hash_obj(&scope, Interpreter::hash(thread, key_obj));
80 if (hash_obj.isErrorException()) {
81 return -1;
82 }
83 word hash = SmallInt::cast(*hash_obj).value();
84
85 setAdd(thread, set, key_obj, hash);
86 return 0;
87}
88
89PY_EXPORT int PySet_Check_Func(PyObject* obj) {
90 return Thread::current()->runtime()->isInstanceOfSet(
91 ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
92}
93
94PY_EXPORT int _PySet_NextEntry(PyObject* pyset, Py_ssize_t* ppos,
95 PyObject** pkey, Py_hash_t* phash) {
96 Thread* thread = Thread::current();
97 HandleScope scope(thread);
98 Object set_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyset)));
99 Runtime* runtime = thread->runtime();
100 if (!runtime->isInstanceOfSetBase(*set_obj)) {
101 thread->raiseBadInternalCall();
102 return -1;
103 }
104 SetBase set(&scope, *set_obj);
105 Object value(&scope, NoneType::object());
106 DCHECK(phash != nullptr, "phash must not be null");
107 DCHECK(pkey != nullptr, "pkey must not be null");
108 if (!setNextItemHash(set, ppos, &value, phash)) {
109 return false;
110 }
111 *pkey = ApiHandle::borrowedReference(runtime, *value);
112 return true;
113}
114
115PY_EXPORT int PySet_Clear(PyObject* anyset) {
116 Thread* thread = Thread::current();
117 Runtime* runtime = thread->runtime();
118 HandleScope scope(thread);
119 Object set_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(anyset)));
120 if (!runtime->isInstanceOfSetBase(*set_obj)) {
121 thread->raiseBadInternalCall();
122 return -1;
123 }
124 SetBase set(&scope, *set_obj);
125 set.setNumItems(0);
126 set.setData(runtime->emptyTuple());
127 return 0;
128}
129
130PY_EXPORT int PySet_Contains(PyObject* anyset, PyObject* key) {
131 Thread* thread = Thread::current();
132 Runtime* runtime = thread->runtime();
133 HandleScope scope(thread);
134
135 Object set_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(anyset)));
136
137 if (!runtime->isInstanceOfSetBase(*set_obj)) {
138 thread->raiseBadInternalCall();
139 return -1;
140 }
141
142 SetBase set(&scope, *set_obj);
143 Object key_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(key)));
144 Object hash_obj(&scope, Interpreter::hash(thread, key_obj));
145 if (hash_obj.isErrorException()) {
146 return -1;
147 }
148 word hash = SmallInt::cast(*hash_obj).value();
149 return setIncludes(thread, set, key_obj, hash);
150}
151
152PY_EXPORT int PySet_Discard(PyObject* pyset, PyObject* pykey) {
153 Thread* thread = Thread::current();
154 Runtime* runtime = thread->runtime();
155 HandleScope scope(thread);
156 Object set_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyset)));
157 if (!runtime->isInstanceOfSet(*set_obj)) {
158 thread->raiseBadInternalCall();
159 return -1;
160 }
161 Set set(&scope, *set_obj);
162 Object key(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pykey)));
163 Object hash_obj(&scope, Interpreter::hash(thread, key));
164 if (hash_obj.isErrorException()) {
165 return -1;
166 }
167 word hash = SmallInt::cast(*hash_obj).value();
168 return setRemove(thread, set, key, hash);
169}
170
171PY_EXPORT PyObject* PySet_New(PyObject* iterable) {
172 Thread* thread = Thread::current();
173 Runtime* runtime = thread->runtime();
174 if (iterable == nullptr) {
175 return ApiHandle::newReferenceWithManaged(runtime, runtime->newSet());
176 }
177
178 HandleScope scope(thread);
179 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(iterable)));
180 Set set(&scope, runtime->newSet());
181
182 Object result(&scope, setUpdate(thread, set, obj));
183 if (result.isError()) {
184 return nullptr;
185 }
186
187 return ApiHandle::newReferenceWithManaged(runtime, *set);
188}
189
190PY_EXPORT PyObject* PySet_Pop(PyObject* pyset) {
191 Thread* thread = Thread::current();
192 Runtime* runtime = thread->runtime();
193 HandleScope scope(thread);
194 Object set_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyset)));
195 if (!runtime->isInstanceOfSet(*set_obj)) {
196 thread->raiseBadInternalCall();
197 return nullptr;
198 }
199 Set set(&scope, *set_obj);
200 Object result(&scope, setPop(thread, set));
201 if (result.isErrorException()) return nullptr;
202 return ApiHandle::newReference(runtime, *result);
203}
204
205PY_EXPORT Py_ssize_t PySet_Size(PyObject* anyset) {
206 Thread* thread = Thread::current();
207 Runtime* runtime = thread->runtime();
208 HandleScope scope(thread);
209
210 Object set_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(anyset)));
211 if (!runtime->isInstanceOfSetBase(*set_obj)) {
212 thread->raiseBadInternalCall();
213 return -1;
214 }
215
216 SetBase set(&scope, *set_obj);
217 return set.numItems();
218}
219
220PY_EXPORT PyTypeObject* PySet_Type_Ptr() {
221 Runtime* runtime = Thread::current()->runtime();
222 return reinterpret_cast<PyTypeObject*>(
223 ApiHandle::borrowedReference(runtime, runtime->typeAt(LayoutId::kSet)));
224}
225
226} // namespace py