blob: af0296d802fd81cab89ebdb20f24d44c58636bb1 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001
Guido van Rossum3f5da241990-12-20 15:06:42 +00002/* Map C struct members to Python object attributes */
3
Guido van Rossum79f25d91997-04-29 20:08:16 +00004#include "Python.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +00005
6#include "structmember.h"
7
Guido van Rossum6f799372001-09-20 20:46:19 +00008PyObject *
Tim Petersc3d12ac2005-12-24 06:03:06 +00009PyMember_GetOne(const char *addr, PyMemberDef *l)
Guido van Rossum6f799372001-09-20 20:46:19 +000010{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000011 PyObject *v;
Guido van Rossuma8add0e2007-05-14 22:03:55 +000012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000013 addr += l->offset;
14 switch (l->type) {
15 case T_BOOL:
16 v = PyBool_FromLong(*(char*)addr);
17 break;
18 case T_BYTE:
19 v = PyLong_FromLong(*(char*)addr);
20 break;
21 case T_UBYTE:
22 v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
23 break;
24 case T_SHORT:
25 v = PyLong_FromLong(*(short*)addr);
26 break;
27 case T_USHORT:
28 v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
29 break;
30 case T_INT:
31 v = PyLong_FromLong(*(int*)addr);
32 break;
33 case T_UINT:
34 v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
35 break;
36 case T_LONG:
37 v = PyLong_FromLong(*(long*)addr);
38 break;
39 case T_ULONG:
40 v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
41 break;
42 case T_PYSSIZET:
43 v = PyLong_FromSsize_t(*(Py_ssize_t*)addr);
44 break;
45 case T_FLOAT:
46 v = PyFloat_FromDouble((double)*(float*)addr);
47 break;
48 case T_DOUBLE:
49 v = PyFloat_FromDouble(*(double*)addr);
50 break;
51 case T_STRING:
52 if (*(char**)addr == NULL) {
53 Py_INCREF(Py_None);
54 v = Py_None;
55 }
56 else
57 v = PyUnicode_FromString(*(char**)addr);
58 break;
59 case T_STRING_INPLACE:
60 v = PyUnicode_FromString((char*)addr);
61 break;
62 case T_CHAR:
63 v = PyUnicode_FromStringAndSize((char*)addr, 1);
64 break;
65 case T_OBJECT:
66 v = *(PyObject **)addr;
67 if (v == NULL)
68 v = Py_None;
69 Py_INCREF(v);
70 break;
71 case T_OBJECT_EX:
72 v = *(PyObject **)addr;
73 if (v == NULL)
74 PyErr_SetString(PyExc_AttributeError, l->name);
75 Py_XINCREF(v);
76 break;
Martin v. Löwis96d743e2005-03-03 23:00:26 +000077#ifdef HAVE_LONG_LONG
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 case T_LONGLONG:
79 v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
80 break;
81 case T_ULONGLONG:
82 v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
83 break;
Martin v. Löwis96d743e2005-03-03 23:00:26 +000084#endif /* HAVE_LONG_LONG */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 case T_NONE:
86 v = Py_None;
87 Py_INCREF(v);
88 break;
89 default:
90 PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
91 v = NULL;
92 }
93 return v;
Guido van Rossum6f799372001-09-20 20:46:19 +000094}
95
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096#define WARN(msg) \
97 do { \
98 if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
99 return -1; \
Guido van Rossum806c2462007-08-06 23:33:07 +0000100 } while (0)
101
Guido van Rossum6f799372001-09-20 20:46:19 +0000102int
103PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
104{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 PyObject *oldv;
Guido van Rossum6f799372001-09-20 20:46:19 +0000106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 addr += l->offset;
Benjamin Petersond12362a2009-12-30 19:44:54 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 if ((l->flags & READONLY))
110 {
111 PyErr_SetString(PyExc_AttributeError, "readonly attribute");
112 return -1;
113 }
114 if (v == NULL) {
115 if (l->type == T_OBJECT_EX) {
116 /* Check if the attribute is set. */
117 if (*(PyObject **)addr == NULL) {
118 PyErr_SetString(PyExc_AttributeError, l->name);
119 return -1;
120 }
121 }
122 else if (l->type != T_OBJECT) {
123 PyErr_SetString(PyExc_TypeError,
124 "can't delete numeric/char attribute");
125 return -1;
126 }
127 }
128 switch (l->type) {
129 case T_BOOL:{
130 if (!PyBool_Check(v)) {
131 PyErr_SetString(PyExc_TypeError,
132 "attribute value type must be bool");
133 return -1;
134 }
135 if (v == Py_True)
136 *(char*)addr = (char) 1;
137 else
138 *(char*)addr = (char) 0;
139 break;
140 }
141 case T_BYTE:{
142 long long_val = PyLong_AsLong(v);
143 if ((long_val == -1) && PyErr_Occurred())
144 return -1;
145 *(char*)addr = (char)long_val;
146 /* XXX: For compatibility, only warn about truncations
147 for now. */
148 if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
149 WARN("Truncation of value to char");
150 break;
151 }
152 case T_UBYTE:{
153 long long_val = PyLong_AsLong(v);
154 if ((long_val == -1) && PyErr_Occurred())
155 return -1;
156 *(unsigned char*)addr = (unsigned char)long_val;
157 if ((long_val > UCHAR_MAX) || (long_val < 0))
158 WARN("Truncation of value to unsigned char");
159 break;
160 }
161 case T_SHORT:{
162 long long_val = PyLong_AsLong(v);
163 if ((long_val == -1) && PyErr_Occurred())
164 return -1;
165 *(short*)addr = (short)long_val;
166 if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
167 WARN("Truncation of value to short");
168 break;
169 }
170 case T_USHORT:{
171 long long_val = PyLong_AsLong(v);
172 if ((long_val == -1) && PyErr_Occurred())
173 return -1;
174 *(unsigned short*)addr = (unsigned short)long_val;
175 if ((long_val > USHRT_MAX) || (long_val < 0))
176 WARN("Truncation of value to unsigned short");
177 break;
178 }
179 case T_INT:{
180 long long_val = PyLong_AsLong(v);
181 if ((long_val == -1) && PyErr_Occurred())
182 return -1;
183 *(int *)addr = (int)long_val;
184 if ((long_val > INT_MAX) || (long_val < INT_MIN))
185 WARN("Truncation of value to int");
186 break;
187 }
188 case T_UINT:{
189 unsigned long ulong_val = PyLong_AsUnsignedLong(v);
190 if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
191 /* XXX: For compatibility, accept negative int values
192 as well. */
193 PyErr_Clear();
194 ulong_val = PyLong_AsLong(v);
195 if ((ulong_val == (unsigned long)-1) &&
196 PyErr_Occurred())
197 return -1;
198 *(unsigned int *)addr = (unsigned int)ulong_val;
199 WARN("Writing negative value into unsigned field");
200 } else
201 *(unsigned int *)addr = (unsigned int)ulong_val;
202 if (ulong_val > UINT_MAX)
203 WARN("Truncation of value to unsigned int");
204 break;
205 }
206 case T_LONG:{
207 *(long*)addr = PyLong_AsLong(v);
208 if ((*(long*)addr == -1) && PyErr_Occurred())
209 return -1;
210 break;
211 }
212 case T_ULONG:{
213 *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
214 if ((*(unsigned long*)addr == (unsigned long)-1)
215 && PyErr_Occurred()) {
216 /* XXX: For compatibility, accept negative int values
217 as well. */
218 PyErr_Clear();
219 *(unsigned long*)addr = PyLong_AsLong(v);
220 if ((*(unsigned long*)addr == (unsigned long)-1)
221 && PyErr_Occurred())
222 return -1;
223 WARN("Writing negative value into unsigned field");
224 }
225 break;
226 }
227 case T_PYSSIZET:{
228 *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
229 if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
230 && PyErr_Occurred())
231 return -1;
232 break;
233 }
234 case T_FLOAT:{
235 double double_val = PyFloat_AsDouble(v);
236 if ((double_val == -1) && PyErr_Occurred())
237 return -1;
238 *(float*)addr = (float)double_val;
239 break;
240 }
241 case T_DOUBLE:
242 *(double*)addr = PyFloat_AsDouble(v);
243 if ((*(double*)addr == -1) && PyErr_Occurred())
244 return -1;
245 break;
246 case T_OBJECT:
247 case T_OBJECT_EX:
248 Py_XINCREF(v);
249 oldv = *(PyObject **)addr;
250 *(PyObject **)addr = v;
251 Py_XDECREF(oldv);
252 break;
253 case T_CHAR: {
254 char *string;
255 Py_ssize_t len;
Alexandre Vassalottia85998a2008-05-03 18:24:43 +0000256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 string = _PyUnicode_AsStringAndSize(v, &len);
Christian Heimes5557a9c2012-09-11 17:30:53 +0200258 if (string == NULL || len != 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000259 PyErr_BadArgument();
260 return -1;
261 }
262 *(char*)addr = string[0];
263 break;
264 }
265 case T_STRING:
266 case T_STRING_INPLACE:
267 PyErr_SetString(PyExc_TypeError, "readonly attribute");
268 return -1;
Martin v. Löwis96d743e2005-03-03 23:00:26 +0000269#ifdef HAVE_LONG_LONG
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 case T_LONGLONG:{
271 PY_LONG_LONG value;
272 *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
273 if ((value == -1) && PyErr_Occurred())
274 return -1;
275 break;
276 }
277 case T_ULONGLONG:{
278 unsigned PY_LONG_LONG value;
279 /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
280 doesn't ??? */
281 if (PyLong_Check(v))
282 *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
283 else
284 *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v);
285 if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
286 return -1;
287 break;
288 }
Martin v. Löwis96d743e2005-03-03 23:00:26 +0000289#endif /* HAVE_LONG_LONG */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290 default:
291 PyErr_Format(PyExc_SystemError,
292 "bad memberdescr type for %s", l->name);
293 return -1;
294 }
295 return 0;
Guido van Rossum6f799372001-09-20 20:46:19 +0000296}