Line data Source code
1 :
2 : /* Map C struct members to Python object attributes */
3 :
4 : #include "Python.h"
5 :
6 : #include "structmember.h"
7 :
8 : static PyObject *
9 0 : listmembers(struct memberlist *mlist)
10 : {
11 : int i, n;
12 : PyObject *v;
13 0 : for (n = 0; mlist[n].name != NULL; n++)
14 : ;
15 0 : v = PyList_New(n);
16 0 : if (v != NULL) {
17 0 : for (i = 0; i < n; i++)
18 0 : PyList_SetItem(v, i,
19 0 : PyString_FromString(mlist[i].name));
20 0 : if (PyErr_Occurred()) {
21 0 : Py_DECREF(v);
22 0 : v = NULL;
23 : }
24 : else {
25 0 : PyList_Sort(v);
26 : }
27 : }
28 0 : return v;
29 : }
30 :
31 : PyObject *
32 0 : PyMember_Get(const char *addr, struct memberlist *mlist, const char *name)
33 : {
34 : struct memberlist *l;
35 :
36 0 : if (strcmp(name, "__members__") == 0)
37 0 : return listmembers(mlist);
38 0 : for (l = mlist; l->name != NULL; l++) {
39 0 : if (strcmp(l->name, name) == 0) {
40 : PyMemberDef copy;
41 0 : copy.name = l->name;
42 0 : copy.type = l->type;
43 0 : copy.offset = l->offset;
44 0 : copy.flags = l->flags;
45 0 : copy.doc = NULL;
46 0 : return PyMember_GetOne(addr, ©);
47 : }
48 : }
49 0 : PyErr_SetString(PyExc_AttributeError, name);
50 0 : return NULL;
51 : }
52 :
53 : PyObject *
54 1035 : PyMember_GetOne(const char *addr, PyMemberDef *l)
55 : {
56 : PyObject *v;
57 1035 : if ((l->flags & READ_RESTRICTED) &&
58 0 : PyEval_GetRestricted()) {
59 0 : PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
60 0 : return NULL;
61 : }
62 1035 : addr += l->offset;
63 1035 : switch (l->type) {
64 : case T_BOOL:
65 0 : v = PyBool_FromLong(*(char*)addr);
66 0 : break;
67 : case T_BYTE:
68 0 : v = PyInt_FromLong(*(char*)addr);
69 0 : break;
70 : case T_UBYTE:
71 0 : v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
72 0 : break;
73 : case T_SHORT:
74 0 : v = PyInt_FromLong(*(short*)addr);
75 0 : break;
76 : case T_USHORT:
77 0 : v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
78 0 : break;
79 : case T_INT:
80 846 : v = PyInt_FromLong(*(int*)addr);
81 846 : break;
82 : case T_UINT:
83 0 : v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
84 0 : break;
85 : case T_LONG:
86 0 : v = PyInt_FromLong(*(long*)addr);
87 0 : break;
88 : case T_ULONG:
89 0 : v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
90 0 : break;
91 : case T_PYSSIZET:
92 0 : v = PyInt_FromSsize_t(*(Py_ssize_t*)addr);
93 0 : break;
94 : case T_FLOAT:
95 0 : v = PyFloat_FromDouble((double)*(float*)addr);
96 0 : break;
97 : case T_DOUBLE:
98 0 : v = PyFloat_FromDouble(*(double*)addr);
99 0 : break;
100 : case T_STRING:
101 0 : if (*(char**)addr == NULL) {
102 0 : Py_INCREF(Py_None);
103 0 : v = Py_None;
104 : }
105 : else
106 0 : v = PyString_FromString(*(char**)addr);
107 0 : break;
108 : case T_STRING_INPLACE:
109 0 : v = PyString_FromString((char*)addr);
110 0 : break;
111 : case T_CHAR:
112 0 : v = PyString_FromStringAndSize((char*)addr, 1);
113 0 : break;
114 : case T_OBJECT:
115 189 : v = *(PyObject **)addr;
116 189 : if (v == NULL)
117 0 : v = Py_None;
118 189 : Py_INCREF(v);
119 189 : break;
120 : case T_OBJECT_EX:
121 0 : v = *(PyObject **)addr;
122 0 : if (v == NULL)
123 0 : PyErr_SetString(PyExc_AttributeError, l->name);
124 0 : Py_XINCREF(v);
125 0 : break;
126 : #ifdef HAVE_LONG_LONG
127 : case T_LONGLONG:
128 0 : v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
129 0 : break;
130 : case T_ULONGLONG:
131 0 : v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
132 0 : break;
133 : #endif /* HAVE_LONG_LONG */
134 : default:
135 0 : PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
136 0 : v = NULL;
137 : }
138 1035 : return v;
139 : }
140 :
141 : int
142 0 : PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v)
143 : {
144 : struct memberlist *l;
145 :
146 0 : for (l = mlist; l->name != NULL; l++) {
147 0 : if (strcmp(l->name, name) == 0) {
148 : PyMemberDef copy;
149 0 : copy.name = l->name;
150 0 : copy.type = l->type;
151 0 : copy.offset = l->offset;
152 0 : copy.flags = l->flags;
153 0 : copy.doc = NULL;
154 0 : return PyMember_SetOne(addr, ©, v);
155 : }
156 : }
157 :
158 0 : PyErr_SetString(PyExc_AttributeError, name);
159 0 : return -1;
160 : }
161 :
162 : #define WARN(msg) \
163 : do { \
164 : if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
165 : return -1; \
166 : } while (0)
167 :
168 : int
169 9 : PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
170 : {
171 : PyObject *oldv;
172 :
173 9 : addr += l->offset;
174 :
175 9 : if ((l->flags & READONLY))
176 : {
177 0 : PyErr_SetString(PyExc_TypeError, "readonly attribute");
178 0 : return -1;
179 : }
180 9 : if ((l->flags & PY_WRITE_RESTRICTED) && PyEval_GetRestricted()) {
181 0 : PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
182 0 : return -1;
183 : }
184 9 : if (v == NULL) {
185 0 : if (l->type == T_OBJECT_EX) {
186 : /* Check if the attribute is set. */
187 0 : if (*(PyObject **)addr == NULL) {
188 0 : PyErr_SetString(PyExc_AttributeError, l->name);
189 0 : return -1;
190 : }
191 : }
192 0 : else if (l->type != T_OBJECT) {
193 0 : PyErr_SetString(PyExc_TypeError,
194 : "can't delete numeric/char attribute");
195 0 : return -1;
196 : }
197 : }
198 9 : switch (l->type) {
199 : case T_BOOL:{
200 0 : if (!PyBool_Check(v)) {
201 0 : PyErr_SetString(PyExc_TypeError,
202 : "attribute value type must be bool");
203 0 : return -1;
204 : }
205 0 : if (v == Py_True)
206 0 : *(char*)addr = (char) 1;
207 : else
208 0 : *(char*)addr = (char) 0;
209 0 : break;
210 : }
211 : case T_BYTE:{
212 0 : long long_val = PyInt_AsLong(v);
213 0 : if ((long_val == -1) && PyErr_Occurred())
214 0 : return -1;
215 0 : *(char*)addr = (char)long_val;
216 : /* XXX: For compatibility, only warn about truncations
217 : for now. */
218 0 : if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
219 0 : WARN("Truncation of value to char");
220 0 : break;
221 : }
222 : case T_UBYTE:{
223 0 : long long_val = PyInt_AsLong(v);
224 0 : if ((long_val == -1) && PyErr_Occurred())
225 0 : return -1;
226 0 : *(unsigned char*)addr = (unsigned char)long_val;
227 0 : if ((long_val > UCHAR_MAX) || (long_val < 0))
228 0 : WARN("Truncation of value to unsigned char");
229 0 : break;
230 : }
231 : case T_SHORT:{
232 0 : long long_val = PyInt_AsLong(v);
233 0 : if ((long_val == -1) && PyErr_Occurred())
234 0 : return -1;
235 0 : *(short*)addr = (short)long_val;
236 0 : if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
237 0 : WARN("Truncation of value to short");
238 0 : break;
239 : }
240 : case T_USHORT:{
241 0 : long long_val = PyInt_AsLong(v);
242 0 : if ((long_val == -1) && PyErr_Occurred())
243 0 : return -1;
244 0 : *(unsigned short*)addr = (unsigned short)long_val;
245 0 : if ((long_val > USHRT_MAX) || (long_val < 0))
246 0 : WARN("Truncation of value to unsigned short");
247 0 : break;
248 : }
249 : case T_INT:{
250 0 : long long_val = PyInt_AsLong(v);
251 0 : if ((long_val == -1) && PyErr_Occurred())
252 0 : return -1;
253 0 : *(int *)addr = (int)long_val;
254 0 : if ((long_val > INT_MAX) || (long_val < INT_MIN))
255 0 : WARN("Truncation of value to int");
256 0 : break;
257 : }
258 : case T_UINT:{
259 0 : unsigned long ulong_val = PyLong_AsUnsignedLong(v);
260 0 : if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
261 : /* XXX: For compatibility, accept negative int values
262 : as well. */
263 0 : PyErr_Clear();
264 0 : ulong_val = PyLong_AsLong(v);
265 0 : if ((ulong_val == (unsigned long)-1) &&
266 0 : PyErr_Occurred())
267 0 : return -1;
268 0 : *(unsigned int *)addr = (unsigned int)ulong_val;
269 0 : WARN("Writing negative value into unsigned field");
270 : } else
271 0 : *(unsigned int *)addr = (unsigned int)ulong_val;
272 0 : if (ulong_val > UINT_MAX)
273 0 : WARN("Truncation of value to unsigned int");
274 0 : break;
275 : }
276 : case T_LONG:{
277 0 : *(long*)addr = PyLong_AsLong(v);
278 0 : if ((*(long*)addr == -1) && PyErr_Occurred())
279 0 : return -1;
280 0 : break;
281 : }
282 : case T_ULONG:{
283 0 : *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
284 0 : if ((*(unsigned long*)addr == (unsigned long)-1)
285 0 : && PyErr_Occurred()) {
286 : /* XXX: For compatibility, accept negative int values
287 : as well. */
288 0 : PyErr_Clear();
289 0 : *(unsigned long*)addr = PyLong_AsLong(v);
290 0 : if ((*(unsigned long*)addr == (unsigned long)-1)
291 0 : && PyErr_Occurred())
292 0 : return -1;
293 0 : WARN("Writing negative value into unsigned field");
294 : }
295 0 : break;
296 : }
297 : case T_PYSSIZET:{
298 0 : *(Py_ssize_t*)addr = PyInt_AsSsize_t(v);
299 0 : if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
300 0 : && PyErr_Occurred())
301 0 : return -1;
302 0 : break;
303 : }
304 : case T_FLOAT:{
305 0 : double double_val = PyFloat_AsDouble(v);
306 0 : if ((double_val == -1) && PyErr_Occurred())
307 0 : return -1;
308 0 : *(float*)addr = (float)double_val;
309 0 : break;
310 : }
311 : case T_DOUBLE:
312 0 : *(double*)addr = PyFloat_AsDouble(v);
313 0 : if ((*(double*)addr == -1) && PyErr_Occurred())
314 0 : return -1;
315 0 : break;
316 : case T_OBJECT:
317 : case T_OBJECT_EX:
318 9 : Py_XINCREF(v);
319 9 : oldv = *(PyObject **)addr;
320 9 : *(PyObject **)addr = v;
321 9 : Py_XDECREF(oldv);
322 9 : break;
323 : case T_CHAR:
324 0 : if (PyString_Check(v) && PyString_Size(v) == 1) {
325 0 : *(char*)addr = PyString_AsString(v)[0];
326 : }
327 : else {
328 0 : PyErr_BadArgument();
329 0 : return -1;
330 : }
331 0 : break;
332 : case T_STRING:
333 : case T_STRING_INPLACE:
334 0 : PyErr_SetString(PyExc_TypeError, "readonly attribute");
335 0 : return -1;
336 : #ifdef HAVE_LONG_LONG
337 : case T_LONGLONG:{
338 : PY_LONG_LONG value;
339 0 : *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
340 0 : if ((value == -1) && PyErr_Occurred())
341 0 : return -1;
342 0 : break;
343 : }
344 : case T_ULONGLONG:{
345 : unsigned PY_LONG_LONG value;
346 : /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
347 : doesn't ??? */
348 0 : if (PyLong_Check(v))
349 0 : *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
350 : else
351 0 : *(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v);
352 0 : if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
353 0 : return -1;
354 0 : break;
355 : }
356 : #endif /* HAVE_LONG_LONG */
357 : default:
358 0 : PyErr_Format(PyExc_SystemError,
359 : "bad memberdescr type for %s", l->name);
360 0 : return -1;
361 : }
362 9 : return 0;
363 : }
|