• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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