blob: ed347834fae7c66c029411ecbd252def742c0ee7 [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 Rossum79f25d91997-04-29 20:08:16 +00008static PyObject *
Thomas Woutersf70ef4f2000-07-22 18:47:25 +00009listmembers(struct memberlist *mlist)
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000010{
11 int i, n;
Guido van Rossum79f25d91997-04-29 20:08:16 +000012 PyObject *v;
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000013 for (n = 0; mlist[n].name != NULL; n++)
14 ;
Guido van Rossum79f25d91997-04-29 20:08:16 +000015 v = PyList_New(n);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000016 if (v != NULL) {
17 for (i = 0; i < n; i++)
Guido van Rossum79f25d91997-04-29 20:08:16 +000018 PyList_SetItem(v, i,
19 PyString_FromString(mlist[i].name));
20 if (PyErr_Occurred()) {
21 Py_DECREF(v);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000022 v = NULL;
23 }
24 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +000025 PyList_Sort(v);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000026 }
27 }
28 return v;
29}
30
Guido van Rossum79f25d91997-04-29 20:08:16 +000031PyObject *
Thomas Woutersf70ef4f2000-07-22 18:47:25 +000032PyMember_Get(char *addr, struct memberlist *mlist, char *name)
Guido van Rossum3f5da241990-12-20 15:06:42 +000033{
34 struct memberlist *l;
35
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000036 if (strcmp(name, "__members__") == 0)
37 return listmembers(mlist);
Guido van Rossum3f5da241990-12-20 15:06:42 +000038 for (l = mlist; l->name != NULL; l++) {
39 if (strcmp(l->name, name) == 0) {
Guido van Rossum79f25d91997-04-29 20:08:16 +000040 PyObject *v;
Guido van Rossumc299fc12001-09-17 19:28:08 +000041 if ((l->flags & READ_RESTRICTED) &&
42 PyEval_GetRestricted()) {
43 PyErr_SetString(PyExc_RuntimeError,
44 "restricted attribute");
45 return NULL;
46 }
Guido van Rossum3f5da241990-12-20 15:06:42 +000047 addr += l->offset;
48 switch (l->type) {
Guido van Rossumab2490a1992-06-03 17:07:23 +000049 case T_BYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000050 v = PyInt_FromLong((long)
Guido van Rossumab2490a1992-06-03 17:07:23 +000051 (((*(char*)addr & 0xff)
52 ^ 0x80) - 0x80));
53 break;
54 case T_UBYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000055 v = PyInt_FromLong((long) *(char*)addr & 0xff);
Guido van Rossumab2490a1992-06-03 17:07:23 +000056 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000057 case T_SHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000058 v = PyInt_FromLong((long) *(short*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000059 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000060 case T_USHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000061 v = PyInt_FromLong((long)
Guido van Rossumab2490a1992-06-03 17:07:23 +000062 *(unsigned short*)addr);
63 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000064 case T_INT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000065 v = PyInt_FromLong((long) *(int*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000066 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000067 case T_UINT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000068 v = PyInt_FromLong((long)
69 *(unsigned int*)addr);
Guido van Rossumab2490a1992-06-03 17:07:23 +000070 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000071 case T_LONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +000072 v = PyInt_FromLong(*(long*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000073 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000074 case T_ULONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +000075 v = PyLong_FromDouble((double)
Guido van Rossumab2490a1992-06-03 17:07:23 +000076 *(unsigned long*)addr);
77 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000078 case T_FLOAT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000079 v = PyFloat_FromDouble((double)*(float*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000080 break;
81 case T_DOUBLE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000082 v = PyFloat_FromDouble(*(double*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000083 break;
84 case T_STRING:
85 if (*(char**)addr == NULL) {
Guido van Rossum79f25d91997-04-29 20:08:16 +000086 Py_INCREF(Py_None);
87 v = Py_None;
Guido van Rossum3f5da241990-12-20 15:06:42 +000088 }
89 else
Guido van Rossum79f25d91997-04-29 20:08:16 +000090 v = PyString_FromString(*(char**)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000091 break;
Jack Jansen599f0d11994-12-14 13:04:05 +000092 case T_STRING_INPLACE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000093 v = PyString_FromString((char*)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +000094 break;
95#ifdef macintosh
96 case T_PSTRING:
97 if (*(char**)addr == NULL) {
Guido van Rossum79f25d91997-04-29 20:08:16 +000098 Py_INCREF(Py_None);
99 v = Py_None;
Jack Jansen599f0d11994-12-14 13:04:05 +0000100 }
101 else
Guido van Rossum79f25d91997-04-29 20:08:16 +0000102 v = PyString_FromStringAndSize(
103 (*(char**)addr)+1,
104 **(unsigned char**)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000105 break;
106 case T_PSTRING_INPLACE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000107 v = PyString_FromStringAndSize(
108 ((char*)addr)+1,
109 *(unsigned char*)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000110 break;
111#endif /* macintosh */
Guido van Rossumab2490a1992-06-03 17:07:23 +0000112 case T_CHAR:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000113 v = PyString_FromStringAndSize((char*)addr, 1);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000114 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000115 case T_OBJECT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000116 v = *(PyObject **)addr;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000117 if (v == NULL)
Guido van Rossum79f25d91997-04-29 20:08:16 +0000118 v = Py_None;
119 Py_INCREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000120 break;
121 default:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000122 PyErr_SetString(PyExc_SystemError,
123 "bad memberlist type");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000124 v = NULL;
125 }
126 return v;
127 }
128 }
129
Guido van Rossum79f25d91997-04-29 20:08:16 +0000130 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000131 return NULL;
132}
133
134int
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000135PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000136{
137 struct memberlist *l;
Guido van Rossumadf0e431998-05-20 22:25:32 +0000138 PyObject *oldv;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000139
140 for (l = mlist; l->name != NULL; l++) {
141 if (strcmp(l->name, name) == 0) {
Guido van Rossumc299fc12001-09-17 19:28:08 +0000142 if ((l->flags & READONLY) || l->type == T_STRING
Jack Jansen599f0d11994-12-14 13:04:05 +0000143#ifdef macintosh
Guido van Rossumc299fc12001-09-17 19:28:08 +0000144 || l->type == T_PSTRING
145#endif
146 )
Guido van Rossum79f25d91997-04-29 20:08:16 +0000147 {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000148 PyErr_SetString(PyExc_TypeError,
149 "readonly attribute");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000150 return -1;
151 }
Guido van Rossumc299fc12001-09-17 19:28:08 +0000152 if ((l->flags & WRITE_RESTRICTED) &&
153 PyEval_GetRestricted()) {
154 PyErr_SetString(PyExc_RuntimeError,
155 "restricted attribute");
156 return -1;
157 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000158 if (v == NULL && l->type != T_OBJECT) {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000159 PyErr_SetString(PyExc_TypeError,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000160 "can't delete numeric/char attribute");
161 return -1;
162 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000163 addr += l->offset;
164 switch (l->type) {
Guido van Rossumab2490a1992-06-03 17:07:23 +0000165 case T_BYTE:
166 case T_UBYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000167 if (!PyInt_Check(v)) {
168 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000169 return -1;
170 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000171 *(char*)addr = (char) PyInt_AsLong(v);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000172 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000173 case T_SHORT:
Guido van Rossumab2490a1992-06-03 17:07:23 +0000174 case T_USHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000175 if (!PyInt_Check(v)) {
176 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000177 return -1;
178 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000179 *(short*)addr = (short) PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000180 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000181 case T_UINT:
Guido van Rossum3f5da241990-12-20 15:06:42 +0000182 case T_INT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000183 if (!PyInt_Check(v)) {
184 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000185 return -1;
186 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000187 *(int*)addr = (int) PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000188 break;
189 case T_LONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000190 if (!PyInt_Check(v)) {
191 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000192 return -1;
193 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000194 *(long*)addr = PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000195 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000196 case T_ULONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000197 if (PyInt_Check(v))
198 *(long*)addr = PyInt_AsLong(v);
199 else if (PyLong_Check(v))
200 *(long*)addr = PyLong_AsLong(v);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000201 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000202 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000203 return -1;
204 }
205 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000206 case T_FLOAT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000207 if (PyInt_Check(v))
Guido van Rossum644a12b1997-04-09 19:24:53 +0000208 *(float*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000209 (float) PyInt_AsLong(v);
210 else if (PyFloat_Check(v))
211 *(float*)addr =
212 (float) PyFloat_AsDouble(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000213 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000214 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000215 return -1;
216 }
217 break;
218 case T_DOUBLE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000219 if (PyInt_Check(v))
Guido van Rossum644a12b1997-04-09 19:24:53 +0000220 *(double*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000221 (double) PyInt_AsLong(v);
222 else if (PyFloat_Check(v))
223 *(double*)addr = PyFloat_AsDouble(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000224 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000225 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000226 return -1;
227 }
228 break;
229 case T_OBJECT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000230 Py_XINCREF(v);
Guido van Rossumadf0e431998-05-20 22:25:32 +0000231 oldv = *(PyObject **)addr;
Guido van Rossum79f25d91997-04-29 20:08:16 +0000232 *(PyObject **)addr = v;
Guido van Rossumadf0e431998-05-20 22:25:32 +0000233 Py_XDECREF(oldv);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000234 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000235 case T_CHAR:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000236 if (PyString_Check(v) &&
237 PyString_Size(v) == 1) {
Guido van Rossumab2490a1992-06-03 17:07:23 +0000238 *(char*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000239 PyString_AsString(v)[0];
Guido van Rossumab2490a1992-06-03 17:07:23 +0000240 }
241 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000242 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000243 return -1;
244 }
Tim Peters547397c2001-01-27 06:20:08 +0000245 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000246 default:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000247 PyErr_SetString(PyExc_SystemError,
248 "bad memberlist type");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000249 return -1;
250 }
251 return 0;
252 }
253 }
254
Guido van Rossum79f25d91997-04-29 20:08:16 +0000255 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum73531a31990-12-20 23:12:40 +0000256 return -1;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000257}