1 #include "parts.h"
2 #include "util.h"
3
4 static PyObject *
dict_containsstring(PyObject * self,PyObject * args)5 dict_containsstring(PyObject *self, PyObject *args)
6 {
7 PyObject *obj;
8 const char *key;
9 Py_ssize_t size;
10 if (!PyArg_ParseTuple(args, "Oz#", &obj, &key, &size)) {
11 return NULL;
12 }
13 NULLABLE(obj);
14 RETURN_INT(PyDict_ContainsString(obj, key));
15 }
16
17 static PyObject *
dict_getitemref(PyObject * self,PyObject * args)18 dict_getitemref(PyObject *self, PyObject *args)
19 {
20 PyObject *obj, *attr_name, *value = UNINITIALIZED_PTR;
21 if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) {
22 return NULL;
23 }
24 NULLABLE(obj);
25 NULLABLE(attr_name);
26
27 switch (PyDict_GetItemRef(obj, attr_name, &value)) {
28 case -1:
29 assert(value == NULL);
30 return NULL;
31 case 0:
32 assert(value == NULL);
33 return Py_NewRef(PyExc_KeyError);
34 case 1:
35 return value;
36 default:
37 Py_FatalError("PyMapping_GetItemRef() returned invalid code");
38 Py_UNREACHABLE();
39 }
40 }
41
42 static PyObject *
dict_getitemstringref(PyObject * self,PyObject * args)43 dict_getitemstringref(PyObject *self, PyObject *args)
44 {
45 PyObject *obj, *value = UNINITIALIZED_PTR;
46 const char *attr_name;
47 Py_ssize_t size;
48 if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) {
49 return NULL;
50 }
51 NULLABLE(obj);
52
53 switch (PyDict_GetItemStringRef(obj, attr_name, &value)) {
54 case -1:
55 assert(value == NULL);
56 return NULL;
57 case 0:
58 assert(value == NULL);
59 return Py_NewRef(PyExc_KeyError);
60 case 1:
61 return value;
62 default:
63 Py_FatalError("PyDict_GetItemStringRef() returned invalid code");
64 Py_UNREACHABLE();
65 }
66 }
67
68 static PyObject *
dict_setdefault(PyObject * self,PyObject * args)69 dict_setdefault(PyObject *self, PyObject *args)
70 {
71 PyObject *mapping, *key, *defaultobj;
72 if (!PyArg_ParseTuple(args, "OOO", &mapping, &key, &defaultobj)) {
73 return NULL;
74 }
75 NULLABLE(mapping);
76 NULLABLE(key);
77 NULLABLE(defaultobj);
78 return PyDict_SetDefault(mapping, key, defaultobj);
79 }
80
81 static PyObject *
dict_setdefaultref(PyObject * self,PyObject * args)82 dict_setdefaultref(PyObject *self, PyObject *args)
83 {
84 PyObject *obj, *key, *default_value, *result = UNINITIALIZED_PTR;
85 if (!PyArg_ParseTuple(args, "OOO", &obj, &key, &default_value)) {
86 return NULL;
87 }
88 NULLABLE(obj);
89 NULLABLE(key);
90 NULLABLE(default_value);
91 switch (PyDict_SetDefaultRef(obj, key, default_value, &result)) {
92 case -1:
93 assert(result == NULL);
94 return NULL;
95 case 0:
96 assert(result == default_value);
97 return result;
98 case 1:
99 return result;
100 default:
101 Py_FatalError("PyDict_SetDefaultRef() returned invalid code");
102 Py_UNREACHABLE();
103 }
104 }
105
106 static PyObject *
dict_pop(PyObject * self,PyObject * args)107 dict_pop(PyObject *self, PyObject *args)
108 {
109 // Test PyDict_Pop(dict, key, &value)
110 PyObject *dict, *key;
111 if (!PyArg_ParseTuple(args, "OO", &dict, &key)) {
112 return NULL;
113 }
114 NULLABLE(dict);
115 NULLABLE(key);
116 PyObject *result = UNINITIALIZED_PTR;
117 int res = PyDict_Pop(dict, key, &result);
118 if (res < 0) {
119 assert(result == NULL);
120 return NULL;
121 }
122 if (res == 0) {
123 assert(result == NULL);
124 result = Py_NewRef(Py_None);
125 }
126 else {
127 assert(result != NULL);
128 }
129 return Py_BuildValue("iN", res, result);
130 }
131
132 static PyObject *
dict_pop_null(PyObject * self,PyObject * args)133 dict_pop_null(PyObject *self, PyObject *args)
134 {
135 // Test PyDict_Pop(dict, key, NULL)
136 PyObject *dict, *key;
137 if (!PyArg_ParseTuple(args, "OO", &dict, &key)) {
138 return NULL;
139 }
140 NULLABLE(dict);
141 NULLABLE(key);
142 RETURN_INT(PyDict_Pop(dict, key, NULL));
143 }
144
145 static PyObject *
dict_popstring(PyObject * self,PyObject * args)146 dict_popstring(PyObject *self, PyObject *args)
147 {
148 PyObject *dict;
149 const char *key;
150 Py_ssize_t key_size;
151 if (!PyArg_ParseTuple(args, "Oz#", &dict, &key, &key_size)) {
152 return NULL;
153 }
154 NULLABLE(dict);
155 PyObject *result = UNINITIALIZED_PTR;
156 int res = PyDict_PopString(dict, key, &result);
157 if (res < 0) {
158 assert(result == NULL);
159 return NULL;
160 }
161 if (res == 0) {
162 assert(result == NULL);
163 result = Py_NewRef(Py_None);
164 }
165 else {
166 assert(result != NULL);
167 }
168 return Py_BuildValue("iN", res, result);
169 }
170
171 static PyObject *
dict_popstring_null(PyObject * self,PyObject * args)172 dict_popstring_null(PyObject *self, PyObject *args)
173 {
174 PyObject *dict;
175 const char *key;
176 Py_ssize_t key_size;
177 if (!PyArg_ParseTuple(args, "Oz#", &dict, &key, &key_size)) {
178 return NULL;
179 }
180 NULLABLE(dict);
181 RETURN_INT(PyDict_PopString(dict, key, NULL));
182 }
183
184 static PyObject *
dict_version(PyObject * self,PyObject * dict)185 dict_version(PyObject *self, PyObject *dict)
186 {
187 if (!PyDict_Check(dict)) {
188 PyErr_SetString(PyExc_TypeError, "expected dict");
189 return NULL;
190 }
191 _Py_COMP_DIAG_PUSH
192 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
193 return PyLong_FromUnsignedLongLong(((PyDictObject *)dict)->ma_version_tag);
194 _Py_COMP_DIAG_POP
195 }
196
197 static PyMethodDef test_methods[] = {
198 {"dict_containsstring", dict_containsstring, METH_VARARGS},
199 {"dict_getitemref", dict_getitemref, METH_VARARGS},
200 {"dict_getitemstringref", dict_getitemstringref, METH_VARARGS},
201 {"dict_setdefault", dict_setdefault, METH_VARARGS},
202 {"dict_setdefaultref", dict_setdefaultref, METH_VARARGS},
203 {"dict_pop", dict_pop, METH_VARARGS},
204 {"dict_pop_null", dict_pop_null, METH_VARARGS},
205 {"dict_popstring", dict_popstring, METH_VARARGS},
206 {"dict_popstring_null", dict_popstring_null, METH_VARARGS},
207 {"dict_version", dict_version, METH_O},
208 {NULL},
209 };
210
211 int
_PyTestCapi_Init_Dict(PyObject * m)212 _PyTestCapi_Init_Dict(PyObject *m)
213 {
214 if (PyModule_AddFunctions(m, test_methods) < 0) {
215 return -1;
216 }
217
218 return 0;
219 }
220