blob: f8588ccf81cad07b81d32c0792cbd279e5a19426 [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{
11 PyObject *v;
Guido van Rossuma8add0e2007-05-14 22:03:55 +000012
Guido van Rossum6f799372001-09-20 20:46:19 +000013 addr += l->offset;
14 switch (l->type) {
15 case T_BYTE:
Christian Heimes217cfd12007-12-02 14:31:20 +000016 v = PyLong_FromLong(*(char*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000017 break;
18 case T_UBYTE:
Thomas Wouters89f507f2006-12-13 04:49:30 +000019 v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000020 break;
21 case T_SHORT:
Christian Heimes217cfd12007-12-02 14:31:20 +000022 v = PyLong_FromLong(*(short*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000023 break;
24 case T_USHORT:
Thomas Wouters89f507f2006-12-13 04:49:30 +000025 v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000026 break;
27 case T_INT:
Christian Heimes217cfd12007-12-02 14:31:20 +000028 v = PyLong_FromLong(*(int*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000029 break;
30 case T_UINT:
Thomas Wouters89f507f2006-12-13 04:49:30 +000031 v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000032 break;
33 case T_LONG:
Christian Heimes217cfd12007-12-02 14:31:20 +000034 v = PyLong_FromLong(*(long*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000035 break;
36 case T_ULONG:
Thomas Wouters89f507f2006-12-13 04:49:30 +000037 v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000038 break;
Guido van Rossum7eaf8222007-06-18 17:58:50 +000039 case T_PYSSIZET:
Christian Heimes217cfd12007-12-02 14:31:20 +000040 v = PyLong_FromSsize_t(*(Py_ssize_t*)addr);
Guido van Rossum7eaf8222007-06-18 17:58:50 +000041 break;
Guido van Rossum6f799372001-09-20 20:46:19 +000042 case T_FLOAT:
43 v = PyFloat_FromDouble((double)*(float*)addr);
44 break;
45 case T_DOUBLE:
46 v = PyFloat_FromDouble(*(double*)addr);
47 break;
48 case T_STRING:
49 if (*(char**)addr == NULL) {
50 Py_INCREF(Py_None);
51 v = Py_None;
52 }
53 else
Guido van Rossum21431e82007-10-19 21:48:41 +000054 v = PyUnicode_FromString(*(char**)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000055 break;
56 case T_STRING_INPLACE:
Guido van Rossum21431e82007-10-19 21:48:41 +000057 v = PyUnicode_FromString((char*)addr);
Guido van Rossum6f799372001-09-20 20:46:19 +000058 break;
Guido van Rossum6f799372001-09-20 20:46:19 +000059 case T_CHAR:
Guido van Rossum21431e82007-10-19 21:48:41 +000060 v = PyUnicode_FromStringAndSize((char*)addr, 1);
Guido van Rossum6f799372001-09-20 20:46:19 +000061 break;
62 case T_OBJECT:
63 v = *(PyObject **)addr;
64 if (v == NULL)
65 v = Py_None;
66 Py_INCREF(v);
67 break;
Guido van Rossum6b705992001-12-04 16:23:42 +000068 case T_OBJECT_EX:
69 v = *(PyObject **)addr;
70 if (v == NULL)
71 PyErr_SetString(PyExc_AttributeError, l->name);
72 Py_XINCREF(v);
73 break;
Martin v. Löwis96d743e2005-03-03 23:00:26 +000074#ifdef HAVE_LONG_LONG
75 case T_LONGLONG:
76 v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
77 break;
78 case T_ULONGLONG:
79 v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
80 break;
81#endif /* HAVE_LONG_LONG */
Guido van Rossum50e9fb92006-08-17 05:42:55 +000082 case T_NONE:
83 v = Py_None;
84 Py_INCREF(v);
85 break;
Guido van Rossum6f799372001-09-20 20:46:19 +000086 default:
87 PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
88 v = NULL;
89 }
90 return v;
91}
92
Skip Montanaro46fc3372007-08-12 11:44:53 +000093#define WARN(msg) \
94 do { \
95 if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
96 return -1; \
Guido van Rossum806c2462007-08-06 23:33:07 +000097 } while (0)
98
Guido van Rossum6f799372001-09-20 20:46:19 +000099int
100PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
101{
102 PyObject *oldv;
103
Jack Janseneddc1442003-11-20 01:44:59 +0000104 if ((l->flags & READONLY) || l->type == T_STRING)
Guido van Rossum6f799372001-09-20 20:46:19 +0000105 {
Collin Winter42dae6a2007-03-28 21:44:53 +0000106 PyErr_SetString(PyExc_AttributeError, "readonly attribute");
Guido van Rossum6f799372001-09-20 20:46:19 +0000107 return -1;
108 }
Guido van Rossum6b705992001-12-04 16:23:42 +0000109 if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) {
Guido van Rossum6f799372001-09-20 20:46:19 +0000110 PyErr_SetString(PyExc_TypeError,
111 "can't delete numeric/char attribute");
112 return -1;
113 }
114 addr += l->offset;
115 switch (l->type) {
Thomas Wouters89f507f2006-12-13 04:49:30 +0000116 case T_BYTE:{
Christian Heimes217cfd12007-12-02 14:31:20 +0000117 long long_val = PyLong_AsLong(v);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000118 if ((long_val == -1) && PyErr_Occurred())
Guido van Rossum6f799372001-09-20 20:46:19 +0000119 return -1;
Guido van Rossum806c2462007-08-06 23:33:07 +0000120 *(char*)addr = (char)long_val;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000121 /* XXX: For compatibility, only warn about truncations
122 for now. */
123 if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
Guido van Rossum806c2462007-08-06 23:33:07 +0000124 WARN("Truncation of value to char");
Guido van Rossum6f799372001-09-20 20:46:19 +0000125 break;
Guido van Rossum6f799372001-09-20 20:46:19 +0000126 }
Thomas Wouters89f507f2006-12-13 04:49:30 +0000127 case T_UBYTE:{
Christian Heimes217cfd12007-12-02 14:31:20 +0000128 long long_val = PyLong_AsLong(v);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000129 if ((long_val == -1) && PyErr_Occurred())
Guido van Rossum6f799372001-09-20 20:46:19 +0000130 return -1;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000131 *(unsigned char*)addr = (unsigned char)long_val;
Guido van Rossum806c2462007-08-06 23:33:07 +0000132 if ((long_val > UCHAR_MAX) || (long_val < 0))
133 WARN("Truncation of value to unsigned char");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000134 break;
Guido van Rossum6f799372001-09-20 20:46:19 +0000135 }
Thomas Wouters89f507f2006-12-13 04:49:30 +0000136 case T_SHORT:{
Christian Heimes217cfd12007-12-02 14:31:20 +0000137 long long_val = PyLong_AsLong(v);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000138 if ((long_val == -1) && PyErr_Occurred())
Guido van Rossum6f799372001-09-20 20:46:19 +0000139 return -1;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000140 *(short*)addr = (short)long_val;
Guido van Rossum806c2462007-08-06 23:33:07 +0000141 if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
142 WARN("Truncation of value to short");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000143 break;
Guido van Rossum6f799372001-09-20 20:46:19 +0000144 }
Thomas Wouters89f507f2006-12-13 04:49:30 +0000145 case T_USHORT:{
Christian Heimes217cfd12007-12-02 14:31:20 +0000146 long long_val = PyLong_AsLong(v);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000147 if ((long_val == -1) && PyErr_Occurred())
Guido van Rossum6f799372001-09-20 20:46:19 +0000148 return -1;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000149 *(unsigned short*)addr = (unsigned short)long_val;
Guido van Rossum806c2462007-08-06 23:33:07 +0000150 if ((long_val > USHRT_MAX) || (long_val < 0))
151 WARN("Truncation of value to unsigned short");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000152 break;
153 }
154 case T_INT:{
Christian Heimes217cfd12007-12-02 14:31:20 +0000155 long long_val = PyLong_AsLong(v);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000156 if ((long_val == -1) && PyErr_Occurred())
157 return -1;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000158 *(int *)addr = (int)long_val;
Guido van Rossum806c2462007-08-06 23:33:07 +0000159 if ((long_val > INT_MAX) || (long_val < INT_MIN))
160 WARN("Truncation of value to int");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000161 break;
162 }
163 case T_UINT:{
Guido van Rossum806c2462007-08-06 23:33:07 +0000164 unsigned long ulong_val = PyLong_AsUnsignedLong(v);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000165 if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
166 /* XXX: For compatibility, accept negative int values
167 as well. */
168 PyErr_Clear();
169 ulong_val = PyLong_AsLong(v);
170 if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
171 return -1;
Guido van Rossum806c2462007-08-06 23:33:07 +0000172 *(unsigned int *)addr = (unsigned int)ulong_val;
173 WARN("Writing negative value into unsigned field");
174 } else
175 *(unsigned int *)addr = (unsigned int)ulong_val;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000176 if (ulong_val > UINT_MAX)
Guido van Rossum806c2462007-08-06 23:33:07 +0000177 WARN("Truncation of value to unsigned int");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000178 break;
179 }
180 case T_LONG:{
181 *(long*)addr = PyLong_AsLong(v);
182 if ((*(long*)addr == -1) && PyErr_Occurred())
183 return -1;
184 break;
185 }
186 case T_ULONG:{
187 *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
188 if ((*(unsigned long*)addr == (unsigned long)-1)
189 && PyErr_Occurred()) {
190 /* XXX: For compatibility, accept negative int values
191 as well. */
192 PyErr_Clear();
193 *(unsigned long*)addr = PyLong_AsLong(v);
Guido van Rossum806c2462007-08-06 23:33:07 +0000194 if ((*(unsigned long*)addr == (unsigned int)-1)
195 && PyErr_Occurred())
Thomas Wouters89f507f2006-12-13 04:49:30 +0000196 return -1;
Guido van Rossum806c2462007-08-06 23:33:07 +0000197 WARN("Writing negative value into unsigned field");
Guido van Rossum6f799372001-09-20 20:46:19 +0000198 }
199 break;
Guido van Rossum6f799372001-09-20 20:46:19 +0000200 }
Guido van Rossum7eaf8222007-06-18 17:58:50 +0000201 case T_PYSSIZET:{
Christian Heimes217cfd12007-12-02 14:31:20 +0000202 *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
Guido van Rossum7eaf8222007-06-18 17:58:50 +0000203 if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
204 && PyErr_Occurred())
205 return -1;
206 break;
207 }
Thomas Wouters89f507f2006-12-13 04:49:30 +0000208 case T_FLOAT:{
Guido van Rossum806c2462007-08-06 23:33:07 +0000209 double double_val = PyFloat_AsDouble(v);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000210 if ((double_val == -1) && PyErr_Occurred())
211 return -1;
212 *(float*)addr = (float)double_val;
Guido van Rossum6f799372001-09-20 20:46:19 +0000213 break;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000214 }
Guido van Rossum6f799372001-09-20 20:46:19 +0000215 case T_DOUBLE:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000216 *(double*)addr = PyFloat_AsDouble(v);
217 if ((*(double*)addr == -1) && PyErr_Occurred())
Guido van Rossum6f799372001-09-20 20:46:19 +0000218 return -1;
Guido van Rossum6f799372001-09-20 20:46:19 +0000219 break;
220 case T_OBJECT:
Guido van Rossum6b705992001-12-04 16:23:42 +0000221 case T_OBJECT_EX:
Guido van Rossum6f799372001-09-20 20:46:19 +0000222 Py_XINCREF(v);
223 oldv = *(PyObject **)addr;
224 *(PyObject **)addr = v;
225 Py_XDECREF(oldv);
226 break;
227 case T_CHAR:
Guido van Rossum21431e82007-10-19 21:48:41 +0000228 if (PyUnicode_Check(v) && PyUnicode_GetSize(v) == 1) {
229 *(char*)addr = PyUnicode_AsString(v)[0];
Guido van Rossum6f799372001-09-20 20:46:19 +0000230 }
231 else {
232 PyErr_BadArgument();
233 return -1;
234 }
235 break;
Martin v. Löwis96d743e2005-03-03 23:00:26 +0000236#ifdef HAVE_LONG_LONG
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000237 case T_LONGLONG:{
238 PY_LONG_LONG value;
239 *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
240 if ((value == -1) && PyErr_Occurred())
Martin v. Löwis96d743e2005-03-03 23:00:26 +0000241 return -1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000242 break;
243 }
244 case T_ULONGLONG:{
245 unsigned PY_LONG_LONG value;
246 /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
247 doesn't ??? */
248 if (PyLong_Check(v))
249 *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
250 else
Christian Heimes217cfd12007-12-02 14:31:20 +0000251 *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v);
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000252 if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
253 return -1;
254 break;
255 }
Martin v. Löwis96d743e2005-03-03 23:00:26 +0000256#endif /* HAVE_LONG_LONG */
Guido van Rossum6f799372001-09-20 20:46:19 +0000257 default:
Jeremy Hylton26633f42001-10-16 16:51:56 +0000258 PyErr_Format(PyExc_SystemError,
259 "bad memberdescr type for %s", l->name);
Guido van Rossum6f799372001-09-20 20:46:19 +0000260 return -1;
261 }
262 return 0;
263}