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 : PyObject *
9 1197 : PyMember_GetOne(const char *addr, PyMemberDef *l)
10 : {
11 : PyObject *v;
12 :
13 1197 : addr += l->offset;
14 1197 : switch (l->type) {
15 : case T_BOOL:
16 0 : v = PyBool_FromLong(*(char*)addr);
17 0 : break;
18 : case T_BYTE:
19 0 : v = PyLong_FromLong(*(char*)addr);
20 0 : break;
21 : case T_UBYTE:
22 0 : v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
23 0 : break;
24 : case T_SHORT:
25 0 : v = PyLong_FromLong(*(short*)addr);
26 0 : break;
27 : case T_USHORT:
28 0 : v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
29 0 : break;
30 : case T_INT:
31 0 : v = PyLong_FromLong(*(int*)addr);
32 0 : break;
33 : case T_UINT:
34 0 : v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
35 0 : break;
36 : case T_LONG:
37 0 : v = PyLong_FromLong(*(long*)addr);
38 0 : break;
39 : case T_ULONG:
40 0 : v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
41 0 : break;
42 : case T_PYSSIZET:
43 0 : v = PyLong_FromSsize_t(*(Py_ssize_t*)addr);
44 0 : break;
45 : case T_FLOAT:
46 0 : v = PyFloat_FromDouble((double)*(float*)addr);
47 0 : break;
48 : case T_DOUBLE:
49 0 : v = PyFloat_FromDouble(*(double*)addr);
50 0 : break;
51 : case T_STRING:
52 0 : if (*(char**)addr == NULL) {
53 0 : Py_INCREF(Py_None);
54 0 : v = Py_None;
55 : }
56 : else
57 0 : v = PyUnicode_FromString(*(char**)addr);
58 0 : break;
59 : case T_STRING_INPLACE:
60 0 : v = PyUnicode_FromString((char*)addr);
61 0 : break;
62 : case T_CHAR:
63 0 : v = PyUnicode_FromStringAndSize((char*)addr, 1);
64 0 : break;
65 : case T_OBJECT:
66 895 : v = *(PyObject **)addr;
67 895 : if (v == NULL)
68 0 : v = Py_None;
69 895 : Py_INCREF(v);
70 895 : break;
71 : case T_OBJECT_EX:
72 302 : v = *(PyObject **)addr;
73 302 : if (v == NULL)
74 0 : PyErr_SetString(PyExc_AttributeError, l->name);
75 302 : Py_XINCREF(v);
76 302 : break;
77 : #ifdef HAVE_LONG_LONG
78 : case T_LONGLONG:
79 0 : v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
80 0 : break;
81 : case T_ULONGLONG:
82 0 : v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
83 0 : break;
84 : #endif /* HAVE_LONG_LONG */
85 : case T_NONE:
86 0 : v = Py_None;
87 0 : Py_INCREF(v);
88 0 : break;
89 : default:
90 0 : PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
91 0 : v = NULL;
92 : }
93 1197 : return v;
94 : }
95 :
96 : #define WARN(msg) \
97 : do { \
98 : if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
99 : return -1; \
100 : } while (0)
101 :
102 : int
103 203 : PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
104 : {
105 : PyObject *oldv;
106 :
107 203 : addr += l->offset;
108 :
109 203 : if ((l->flags & READONLY))
110 : {
111 0 : PyErr_SetString(PyExc_AttributeError, "readonly attribute");
112 0 : return -1;
113 : }
114 203 : if (v == NULL) {
115 0 : if (l->type == T_OBJECT_EX) {
116 : /* Check if the attribute is set. */
117 0 : if (*(PyObject **)addr == NULL) {
118 0 : PyErr_SetString(PyExc_AttributeError, l->name);
119 0 : return -1;
120 : }
121 : }
122 0 : else if (l->type != T_OBJECT) {
123 0 : PyErr_SetString(PyExc_TypeError,
124 : "can't delete numeric/char attribute");
125 0 : return -1;
126 : }
127 : }
128 203 : switch (l->type) {
129 : case T_BOOL:{
130 0 : if (!PyBool_Check(v)) {
131 0 : PyErr_SetString(PyExc_TypeError,
132 : "attribute value type must be bool");
133 0 : return -1;
134 : }
135 0 : if (v == Py_True)
136 0 : *(char*)addr = (char) 1;
137 : else
138 0 : *(char*)addr = (char) 0;
139 0 : break;
140 : }
141 : case T_BYTE:{
142 0 : long long_val = PyLong_AsLong(v);
143 0 : if ((long_val == -1) && PyErr_Occurred())
144 0 : return -1;
145 0 : *(char*)addr = (char)long_val;
146 : /* XXX: For compatibility, only warn about truncations
147 : for now. */
148 0 : if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
149 0 : WARN("Truncation of value to char");
150 0 : break;
151 : }
152 : case T_UBYTE:{
153 0 : long long_val = PyLong_AsLong(v);
154 0 : if ((long_val == -1) && PyErr_Occurred())
155 0 : return -1;
156 0 : *(unsigned char*)addr = (unsigned char)long_val;
157 0 : if ((long_val > UCHAR_MAX) || (long_val < 0))
158 0 : WARN("Truncation of value to unsigned char");
159 0 : break;
160 : }
161 : case T_SHORT:{
162 0 : long long_val = PyLong_AsLong(v);
163 0 : if ((long_val == -1) && PyErr_Occurred())
164 0 : return -1;
165 0 : *(short*)addr = (short)long_val;
166 0 : if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
167 0 : WARN("Truncation of value to short");
168 0 : break;
169 : }
170 : case T_USHORT:{
171 0 : long long_val = PyLong_AsLong(v);
172 0 : if ((long_val == -1) && PyErr_Occurred())
173 0 : return -1;
174 0 : *(unsigned short*)addr = (unsigned short)long_val;
175 0 : if ((long_val > USHRT_MAX) || (long_val < 0))
176 0 : WARN("Truncation of value to unsigned short");
177 0 : break;
178 : }
179 : case T_INT:{
180 0 : long long_val = PyLong_AsLong(v);
181 0 : if ((long_val == -1) && PyErr_Occurred())
182 0 : return -1;
183 0 : *(int *)addr = (int)long_val;
184 : if ((long_val > INT_MAX) || (long_val < INT_MIN))
185 : WARN("Truncation of value to int");
186 0 : break;
187 : }
188 : case T_UINT:{
189 0 : unsigned long ulong_val = PyLong_AsUnsignedLong(v);
190 0 : if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
191 : /* XXX: For compatibility, accept negative int values
192 : as well. */
193 0 : PyErr_Clear();
194 0 : ulong_val = PyLong_AsLong(v);
195 0 : if ((ulong_val == (unsigned long)-1) &&
196 0 : PyErr_Occurred())
197 0 : return -1;
198 0 : *(unsigned int *)addr = (unsigned int)ulong_val;
199 0 : WARN("Writing negative value into unsigned field");
200 : } else
201 0 : *(unsigned int *)addr = (unsigned int)ulong_val;
202 : if (ulong_val > UINT_MAX)
203 : WARN("Truncation of value to unsigned int");
204 0 : break;
205 : }
206 : case T_LONG:{
207 0 : *(long*)addr = PyLong_AsLong(v);
208 0 : if ((*(long*)addr == -1) && PyErr_Occurred())
209 0 : return -1;
210 0 : break;
211 : }
212 : case T_ULONG:{
213 0 : *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
214 0 : if ((*(unsigned long*)addr == (unsigned long)-1)
215 0 : && PyErr_Occurred()) {
216 : /* XXX: For compatibility, accept negative int values
217 : as well. */
218 0 : PyErr_Clear();
219 0 : *(unsigned long*)addr = PyLong_AsLong(v);
220 0 : if ((*(unsigned long*)addr == (unsigned long)-1)
221 0 : && PyErr_Occurred())
222 0 : return -1;
223 0 : WARN("Writing negative value into unsigned field");
224 : }
225 0 : break;
226 : }
227 : case T_PYSSIZET:{
228 0 : *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
229 0 : if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
230 0 : && PyErr_Occurred())
231 0 : return -1;
232 0 : break;
233 : }
234 : case T_FLOAT:{
235 0 : double double_val = PyFloat_AsDouble(v);
236 0 : if ((double_val == -1) && PyErr_Occurred())
237 0 : return -1;
238 0 : *(float*)addr = (float)double_val;
239 0 : break;
240 : }
241 : case T_DOUBLE:
242 0 : *(double*)addr = PyFloat_AsDouble(v);
243 0 : if ((*(double*)addr == -1) && PyErr_Occurred())
244 0 : return -1;
245 0 : break;
246 : case T_OBJECT:
247 : case T_OBJECT_EX:
248 203 : Py_XINCREF(v);
249 203 : oldv = *(PyObject **)addr;
250 203 : *(PyObject **)addr = v;
251 203 : Py_XDECREF(oldv);
252 203 : break;
253 : case T_CHAR: {
254 : char *string;
255 : Py_ssize_t len;
256 :
257 0 : if (!PyUnicode_Check(v)) {
258 0 : PyErr_BadArgument();
259 0 : return -1;
260 : }
261 0 : string = _PyUnicode_AsStringAndSize(v, &len);
262 0 : if (len != 1) {
263 0 : PyErr_BadArgument();
264 0 : return -1;
265 : }
266 0 : *(char*)addr = string[0];
267 : break;
268 : }
269 : case T_STRING:
270 : case T_STRING_INPLACE:
271 0 : PyErr_SetString(PyExc_TypeError, "readonly attribute");
272 0 : return -1;
273 : #ifdef HAVE_LONG_LONG
274 : case T_LONGLONG:{
275 : PY_LONG_LONG value;
276 0 : *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
277 0 : if ((value == -1) && PyErr_Occurred())
278 0 : return -1;
279 0 : break;
280 : }
281 : case T_ULONGLONG:{
282 : unsigned PY_LONG_LONG value;
283 : /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
284 : doesn't ??? */
285 0 : if (PyLong_Check(v))
286 0 : *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
287 : else
288 0 : *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v);
289 0 : if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
290 0 : return -1;
291 0 : break;
292 : }
293 : #endif /* HAVE_LONG_LONG */
294 : default:
295 0 : PyErr_Format(PyExc_SystemError,
296 : "bad memberdescr type for %s", l->name);
297 0 : return -1;
298 : }
299 203 : return 0;
300 : }
|