2 /* Map C struct members to Python object attributes */
6 #include "structmember.h"
9 PyMember_GetOne(const char *addr
, PyMemberDef
*l
)
16 v
= PyBool_FromLong(*(char*)addr
);
19 v
= PyLong_FromLong(*(char*)addr
);
22 v
= PyLong_FromUnsignedLong(*(unsigned char*)addr
);
25 v
= PyLong_FromLong(*(short*)addr
);
28 v
= PyLong_FromUnsignedLong(*(unsigned short*)addr
);
31 v
= PyLong_FromLong(*(int*)addr
);
34 v
= PyLong_FromUnsignedLong(*(unsigned int*)addr
);
37 v
= PyLong_FromLong(*(long*)addr
);
40 v
= PyLong_FromUnsignedLong(*(unsigned long*)addr
);
43 v
= PyLong_FromSsize_t(*(Py_ssize_t
*)addr
);
46 v
= PyFloat_FromDouble((double)*(float*)addr
);
49 v
= PyFloat_FromDouble(*(double*)addr
);
52 if (*(char**)addr
== NULL
) {
57 v
= PyUnicode_FromString(*(char**)addr
);
59 case T_STRING_INPLACE
:
60 v
= PyUnicode_FromString((char*)addr
);
63 v
= PyUnicode_FromStringAndSize((char*)addr
, 1);
66 v
= *(PyObject
**)addr
;
72 v
= *(PyObject
**)addr
;
74 PyErr_SetString(PyExc_AttributeError
, l
->name
);
79 v
= PyLong_FromLongLong(*(PY_LONG_LONG
*)addr
);
82 v
= PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG
*)addr
);
84 #endif /* HAVE_LONG_LONG */
90 PyErr_SetString(PyExc_SystemError
, "bad memberdescr type");
98 if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
103 PyMember_SetOne(char *addr
, PyMemberDef
*l
, PyObject
*v
)
107 if ((l
->flags
& READONLY
) || l
->type
== T_STRING
)
109 PyErr_SetString(PyExc_AttributeError
, "readonly attribute");
112 if (v
== NULL
&& l
->type
!= T_OBJECT_EX
&& l
->type
!= T_OBJECT
) {
113 PyErr_SetString(PyExc_TypeError
,
114 "can't delete numeric/char attribute");
120 if (!PyBool_Check(v
)) {
121 PyErr_SetString(PyExc_TypeError
,
122 "attribute value type must be bool");
126 *(char*)addr
= (char) 1;
128 *(char*)addr
= (char) 0;
132 long long_val
= PyLong_AsLong(v
);
133 if ((long_val
== -1) && PyErr_Occurred())
135 *(char*)addr
= (char)long_val
;
136 /* XXX: For compatibility, only warn about truncations
138 if ((long_val
> CHAR_MAX
) || (long_val
< CHAR_MIN
))
139 WARN("Truncation of value to char");
143 long long_val
= PyLong_AsLong(v
);
144 if ((long_val
== -1) && PyErr_Occurred())
146 *(unsigned char*)addr
= (unsigned char)long_val
;
147 if ((long_val
> UCHAR_MAX
) || (long_val
< 0))
148 WARN("Truncation of value to unsigned char");
152 long long_val
= PyLong_AsLong(v
);
153 if ((long_val
== -1) && PyErr_Occurred())
155 *(short*)addr
= (short)long_val
;
156 if ((long_val
> SHRT_MAX
) || (long_val
< SHRT_MIN
))
157 WARN("Truncation of value to short");
161 long long_val
= PyLong_AsLong(v
);
162 if ((long_val
== -1) && PyErr_Occurred())
164 *(unsigned short*)addr
= (unsigned short)long_val
;
165 if ((long_val
> USHRT_MAX
) || (long_val
< 0))
166 WARN("Truncation of value to unsigned short");
170 long long_val
= PyLong_AsLong(v
);
171 if ((long_val
== -1) && PyErr_Occurred())
173 *(int *)addr
= (int)long_val
;
174 if ((long_val
> INT_MAX
) || (long_val
< INT_MIN
))
175 WARN("Truncation of value to int");
179 unsigned long ulong_val
= PyLong_AsUnsignedLong(v
);
180 if ((ulong_val
== (unsigned int)-1) && PyErr_Occurred()) {
181 /* XXX: For compatibility, accept negative int values
184 ulong_val
= PyLong_AsLong(v
);
185 if ((ulong_val
== (unsigned int)-1) && PyErr_Occurred())
187 *(unsigned int *)addr
= (unsigned int)ulong_val
;
188 WARN("Writing negative value into unsigned field");
190 *(unsigned int *)addr
= (unsigned int)ulong_val
;
191 if (ulong_val
> UINT_MAX
)
192 WARN("Truncation of value to unsigned int");
196 *(long*)addr
= PyLong_AsLong(v
);
197 if ((*(long*)addr
== -1) && PyErr_Occurred())
202 *(unsigned long*)addr
= PyLong_AsUnsignedLong(v
);
203 if ((*(unsigned long*)addr
== (unsigned long)-1)
204 && PyErr_Occurred()) {
205 /* XXX: For compatibility, accept negative int values
208 *(unsigned long*)addr
= PyLong_AsLong(v
);
209 if ((*(unsigned long*)addr
== (unsigned int)-1)
212 WARN("Writing negative value into unsigned field");
217 *(Py_ssize_t
*)addr
= PyLong_AsSsize_t(v
);
218 if ((*(Py_ssize_t
*)addr
== (Py_ssize_t
)-1)
224 double double_val
= PyFloat_AsDouble(v
);
225 if ((double_val
== -1) && PyErr_Occurred())
227 *(float*)addr
= (float)double_val
;
231 *(double*)addr
= PyFloat_AsDouble(v
);
232 if ((*(double*)addr
== -1) && PyErr_Occurred())
238 oldv
= *(PyObject
**)addr
;
239 *(PyObject
**)addr
= v
;
246 if (!PyUnicode_Check(v
)) {
250 string
= _PyUnicode_AsStringAndSize(v
, &len
);
255 *(char*)addr
= string
[0];
258 #ifdef HAVE_LONG_LONG
261 *(PY_LONG_LONG
*)addr
= value
= PyLong_AsLongLong(v
);
262 if ((value
== -1) && PyErr_Occurred())
267 unsigned PY_LONG_LONG value
;
268 /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
271 *(unsigned PY_LONG_LONG
*)addr
= value
= PyLong_AsUnsignedLongLong(v
);
273 *(unsigned PY_LONG_LONG
*)addr
= value
= PyLong_AsLong(v
);
274 if ((value
== (unsigned PY_LONG_LONG
)-1) && PyErr_Occurred())
278 #endif /* HAVE_LONG_LONG */
280 PyErr_Format(PyExc_SystemError
,
281 "bad memberdescr type for %s", l
->name
);