Merged revisions 75246 via svnmerge from
[python/dscho.git] / Python / structmember.c
blob9f08a6baf8e857253d2e0c163585495efd925faf
2 /* Map C struct members to Python object attributes */
4 #include "Python.h"
6 #include "structmember.h"
8 PyObject *
9 PyMember_GetOne(const char *addr, PyMemberDef *l)
11 PyObject *v;
13 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;
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;
77 #ifdef HAVE_LONG_LONG
78 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;
84 #endif /* HAVE_LONG_LONG */
85 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;
93 return v;
96 #define WARN(msg) \
97 do { \
98 if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
99 return -1; \
100 } while (0)
103 PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
105 PyObject *oldv;
107 if ((l->flags & READONLY) || l->type == T_STRING)
109 PyErr_SetString(PyExc_AttributeError, "readonly attribute");
110 return -1;
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");
115 return -1;
117 addr += l->offset;
118 switch (l->type) {
119 case T_BOOL:{
120 if (!PyBool_Check(v)) {
121 PyErr_SetString(PyExc_TypeError,
122 "attribute value type must be bool");
123 return -1;
125 if (v == Py_True)
126 *(char*)addr = (char) 1;
127 else
128 *(char*)addr = (char) 0;
129 break;
131 case T_BYTE:{
132 long long_val = PyLong_AsLong(v);
133 if ((long_val == -1) && PyErr_Occurred())
134 return -1;
135 *(char*)addr = (char)long_val;
136 /* XXX: For compatibility, only warn about truncations
137 for now. */
138 if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
139 WARN("Truncation of value to char");
140 break;
142 case T_UBYTE:{
143 long long_val = PyLong_AsLong(v);
144 if ((long_val == -1) && PyErr_Occurred())
145 return -1;
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");
149 break;
151 case T_SHORT:{
152 long long_val = PyLong_AsLong(v);
153 if ((long_val == -1) && PyErr_Occurred())
154 return -1;
155 *(short*)addr = (short)long_val;
156 if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
157 WARN("Truncation of value to short");
158 break;
160 case T_USHORT:{
161 long long_val = PyLong_AsLong(v);
162 if ((long_val == -1) && PyErr_Occurred())
163 return -1;
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");
167 break;
169 case T_INT:{
170 long long_val = PyLong_AsLong(v);
171 if ((long_val == -1) && PyErr_Occurred())
172 return -1;
173 *(int *)addr = (int)long_val;
174 if ((long_val > INT_MAX) || (long_val < INT_MIN))
175 WARN("Truncation of value to int");
176 break;
178 case T_UINT:{
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
182 as well. */
183 PyErr_Clear();
184 ulong_val = PyLong_AsLong(v);
185 if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
186 return -1;
187 *(unsigned int *)addr = (unsigned int)ulong_val;
188 WARN("Writing negative value into unsigned field");
189 } else
190 *(unsigned int *)addr = (unsigned int)ulong_val;
191 if (ulong_val > UINT_MAX)
192 WARN("Truncation of value to unsigned int");
193 break;
195 case T_LONG:{
196 *(long*)addr = PyLong_AsLong(v);
197 if ((*(long*)addr == -1) && PyErr_Occurred())
198 return -1;
199 break;
201 case T_ULONG:{
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
206 as well. */
207 PyErr_Clear();
208 *(unsigned long*)addr = PyLong_AsLong(v);
209 if ((*(unsigned long*)addr == (unsigned int)-1)
210 && PyErr_Occurred())
211 return -1;
212 WARN("Writing negative value into unsigned field");
214 break;
216 case T_PYSSIZET:{
217 *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
218 if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
219 && PyErr_Occurred())
220 return -1;
221 break;
223 case T_FLOAT:{
224 double double_val = PyFloat_AsDouble(v);
225 if ((double_val == -1) && PyErr_Occurred())
226 return -1;
227 *(float*)addr = (float)double_val;
228 break;
230 case T_DOUBLE:
231 *(double*)addr = PyFloat_AsDouble(v);
232 if ((*(double*)addr == -1) && PyErr_Occurred())
233 return -1;
234 break;
235 case T_OBJECT:
236 case T_OBJECT_EX:
237 Py_XINCREF(v);
238 oldv = *(PyObject **)addr;
239 *(PyObject **)addr = v;
240 Py_XDECREF(oldv);
241 break;
242 case T_CHAR: {
243 char *string;
244 Py_ssize_t len;
246 if (!PyUnicode_Check(v)) {
247 PyErr_BadArgument();
248 return -1;
250 string = _PyUnicode_AsStringAndSize(v, &len);
251 if (len != 1) {
252 PyErr_BadArgument();
253 return -1;
255 *(char*)addr = string[0];
256 break;
258 #ifdef HAVE_LONG_LONG
259 case T_LONGLONG:{
260 PY_LONG_LONG value;
261 *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
262 if ((value == -1) && PyErr_Occurred())
263 return -1;
264 break;
266 case T_ULONGLONG:{
267 unsigned PY_LONG_LONG value;
268 /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
269 doesn't ??? */
270 if (PyLong_Check(v))
271 *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
272 else
273 *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v);
274 if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
275 return -1;
276 break;
278 #endif /* HAVE_LONG_LONG */
279 default:
280 PyErr_Format(PyExc_SystemError,
281 "bad memberdescr type for %s", l->name);
282 return -1;
284 return 0;