Python-2.7.3/Python/structmember.c

No issues found

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