blob: be2737d405e12ccef1d0aabd3e390b6d67491a03 [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;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 case T_LONGLONG:
Benjamin Petersonaf580df2016-09-06 10:46:49 -070078 v = PyLong_FromLongLong(*(long long *)addr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 break;
80 case T_ULONGLONG:
Benjamin Petersonaf580df2016-09-06 10:46:49 -070081 v = PyLong_FromUnsignedLongLong(*(unsigned long long *)addr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 break;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 case T_NONE:
84 v = Py_None;
85 Py_INCREF(v);
86 break;
87 default:
88 PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
89 v = NULL;
90 }
91 return v;
Guido van Rossum6f799372001-09-20 20:46:19 +000092}
93
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094#define WARN(msg) \
95 do { \
96 if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
97 return -1; \
Guido van Rossum806c2462007-08-06 23:33:07 +000098 } while (0)
99
Guido van Rossum6f799372001-09-20 20:46:19 +0000100int
101PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
102{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 PyObject *oldv;
Guido van Rossum6f799372001-09-20 20:46:19 +0000104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 addr += l->offset;
Benjamin Petersond12362a2009-12-30 19:44:54 +0000106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 if ((l->flags & READONLY))
108 {
109 PyErr_SetString(PyExc_AttributeError, "readonly attribute");
110 return -1;
111 }
112 if (v == NULL) {
113 if (l->type == T_OBJECT_EX) {
114 /* Check if the attribute is set. */
115 if (*(PyObject **)addr == NULL) {
116 PyErr_SetString(PyExc_AttributeError, l->name);
117 return -1;
118 }
119 }
120 else if (l->type != T_OBJECT) {
121 PyErr_SetString(PyExc_TypeError,
122 "can't delete numeric/char attribute");
123 return -1;
124 }
125 }
126 switch (l->type) {
127 case T_BOOL:{
128 if (!PyBool_Check(v)) {
129 PyErr_SetString(PyExc_TypeError,
130 "attribute value type must be bool");
131 return -1;
132 }
133 if (v == Py_True)
134 *(char*)addr = (char) 1;
135 else
136 *(char*)addr = (char) 0;
137 break;
138 }
139 case T_BYTE:{
140 long long_val = PyLong_AsLong(v);
141 if ((long_val == -1) && PyErr_Occurred())
142 return -1;
143 *(char*)addr = (char)long_val;
144 /* XXX: For compatibility, only warn about truncations
145 for now. */
146 if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
147 WARN("Truncation of value to char");
148 break;
149 }
150 case T_UBYTE:{
151 long long_val = PyLong_AsLong(v);
152 if ((long_val == -1) && PyErr_Occurred())
153 return -1;
154 *(unsigned char*)addr = (unsigned char)long_val;
155 if ((long_val > UCHAR_MAX) || (long_val < 0))
156 WARN("Truncation of value to unsigned char");
157 break;
158 }
159 case T_SHORT:{
160 long long_val = PyLong_AsLong(v);
161 if ((long_val == -1) && PyErr_Occurred())
162 return -1;
163 *(short*)addr = (short)long_val;
164 if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
165 WARN("Truncation of value to short");
166 break;
167 }
168 case T_USHORT:{
169 long long_val = PyLong_AsLong(v);
170 if ((long_val == -1) && PyErr_Occurred())
171 return -1;
172 *(unsigned short*)addr = (unsigned short)long_val;
173 if ((long_val > USHRT_MAX) || (long_val < 0))
174 WARN("Truncation of value to unsigned short");
175 break;
176 }
177 case T_INT:{
178 long long_val = PyLong_AsLong(v);
179 if ((long_val == -1) && PyErr_Occurred())
180 return -1;
181 *(int *)addr = (int)long_val;
182 if ((long_val > INT_MAX) || (long_val < INT_MIN))
183 WARN("Truncation of value to int");
184 break;
185 }
186 case T_UINT:{
187 unsigned long ulong_val = PyLong_AsUnsignedLong(v);
188 if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
189 /* XXX: For compatibility, accept negative int values
190 as well. */
191 PyErr_Clear();
192 ulong_val = PyLong_AsLong(v);
193 if ((ulong_val == (unsigned long)-1) &&
194 PyErr_Occurred())
195 return -1;
196 *(unsigned int *)addr = (unsigned int)ulong_val;
197 WARN("Writing negative value into unsigned field");
198 } else
199 *(unsigned int *)addr = (unsigned int)ulong_val;
200 if (ulong_val > UINT_MAX)
201 WARN("Truncation of value to unsigned int");
202 break;
203 }
204 case T_LONG:{
205 *(long*)addr = PyLong_AsLong(v);
206 if ((*(long*)addr == -1) && PyErr_Occurred())
207 return -1;
208 break;
209 }
210 case T_ULONG:{
211 *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
212 if ((*(unsigned long*)addr == (unsigned long)-1)
213 && PyErr_Occurred()) {
214 /* XXX: For compatibility, accept negative int values
215 as well. */
216 PyErr_Clear();
217 *(unsigned long*)addr = PyLong_AsLong(v);
218 if ((*(unsigned long*)addr == (unsigned long)-1)
219 && PyErr_Occurred())
220 return -1;
221 WARN("Writing negative value into unsigned field");
222 }
223 break;
224 }
225 case T_PYSSIZET:{
226 *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
227 if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
228 && PyErr_Occurred())
229 return -1;
230 break;
231 }
232 case T_FLOAT:{
233 double double_val = PyFloat_AsDouble(v);
234 if ((double_val == -1) && PyErr_Occurred())
235 return -1;
236 *(float*)addr = (float)double_val;
237 break;
238 }
239 case T_DOUBLE:
240 *(double*)addr = PyFloat_AsDouble(v);
241 if ((*(double*)addr == -1) && PyErr_Occurred())
242 return -1;
243 break;
244 case T_OBJECT:
245 case T_OBJECT_EX:
246 Py_XINCREF(v);
247 oldv = *(PyObject **)addr;
248 *(PyObject **)addr = v;
249 Py_XDECREF(oldv);
250 break;
251 case T_CHAR: {
252 char *string;
253 Py_ssize_t len;
Alexandre Vassalottia85998a2008-05-03 18:24:43 +0000254
Serhiy Storchaka06515832016-11-20 09:13:07 +0200255 string = PyUnicode_AsUTF8AndSize(v, &len);
Christian Heimes5557a9c2012-09-11 17:30:53 +0200256 if (string == NULL || len != 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 PyErr_BadArgument();
258 return -1;
259 }
260 *(char*)addr = string[0];
261 break;
262 }
263 case T_STRING:
264 case T_STRING_INPLACE:
265 PyErr_SetString(PyExc_TypeError, "readonly attribute");
266 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000267 case T_LONGLONG:{
Benjamin Petersonaf580df2016-09-06 10:46:49 -0700268 long long value;
269 *(long long*)addr = value = PyLong_AsLongLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 if ((value == -1) && PyErr_Occurred())
271 return -1;
272 break;
273 }
274 case T_ULONGLONG:{
Benjamin Petersonaf580df2016-09-06 10:46:49 -0700275 unsigned long long value;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276 /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
277 doesn't ??? */
278 if (PyLong_Check(v))
Benjamin Petersonaf580df2016-09-06 10:46:49 -0700279 *(unsigned long long*)addr = value = PyLong_AsUnsignedLongLong(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000280 else
Benjamin Petersonaf580df2016-09-06 10:46:49 -0700281 *(unsigned long long*)addr = value = PyLong_AsLong(v);
282 if ((value == (unsigned long long)-1) && PyErr_Occurred())
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283 return -1;
284 break;
285 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 default:
287 PyErr_Format(PyExc_SystemError,
288 "bad memberdescr type for %s", l->name);
289 return -1;
290 }
291 return 0;
Guido van Rossum6f799372001-09-20 20:46:19 +0000292}