blob: 5b0ca908296a92b40d15535396aec2750b24edb5 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00009******************************************************************/
10
Guido van Rossum3f5da241990-12-20 15:06:42 +000011/* Map C struct members to Python object attributes */
12
Guido van Rossum79f25d91997-04-29 20:08:16 +000013#include "Python.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000014
15#include "structmember.h"
16
Guido van Rossum79f25d91997-04-29 20:08:16 +000017static PyObject *
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000018listmembers(mlist)
19 struct memberlist *mlist;
20{
21 int i, n;
Guido van Rossum79f25d91997-04-29 20:08:16 +000022 PyObject *v;
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000023 for (n = 0; mlist[n].name != NULL; n++)
24 ;
Guido van Rossum79f25d91997-04-29 20:08:16 +000025 v = PyList_New(n);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000026 if (v != NULL) {
27 for (i = 0; i < n; i++)
Guido van Rossum79f25d91997-04-29 20:08:16 +000028 PyList_SetItem(v, i,
29 PyString_FromString(mlist[i].name));
30 if (PyErr_Occurred()) {
31 Py_DECREF(v);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000032 v = NULL;
33 }
34 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +000035 PyList_Sort(v);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000036 }
37 }
38 return v;
39}
40
Guido van Rossum79f25d91997-04-29 20:08:16 +000041PyObject *
42PyMember_Get(addr, mlist, name)
Guido van Rossum3f5da241990-12-20 15:06:42 +000043 char *addr;
44 struct memberlist *mlist;
45 char *name;
46{
47 struct memberlist *l;
48
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000049 if (strcmp(name, "__members__") == 0)
50 return listmembers(mlist);
Guido van Rossum3f5da241990-12-20 15:06:42 +000051 for (l = mlist; l->name != NULL; l++) {
52 if (strcmp(l->name, name) == 0) {
Guido van Rossum79f25d91997-04-29 20:08:16 +000053 PyObject *v;
Guido van Rossum3f5da241990-12-20 15:06:42 +000054 addr += l->offset;
55 switch (l->type) {
Guido van Rossumab2490a1992-06-03 17:07:23 +000056 case T_BYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000057 v = PyInt_FromLong((long)
Guido van Rossumab2490a1992-06-03 17:07:23 +000058 (((*(char*)addr & 0xff)
59 ^ 0x80) - 0x80));
60 break;
61 case T_UBYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000062 v = PyInt_FromLong((long) *(char*)addr & 0xff);
Guido van Rossumab2490a1992-06-03 17:07:23 +000063 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000064 case T_SHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000065 v = PyInt_FromLong((long) *(short*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000066 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000067 case T_USHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000068 v = PyInt_FromLong((long)
Guido van Rossumab2490a1992-06-03 17:07:23 +000069 *(unsigned short*)addr);
70 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000071 case T_INT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000072 v = PyInt_FromLong((long) *(int*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000073 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000074 case T_UINT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000075 v = PyInt_FromLong((long)
76 *(unsigned int*)addr);
Guido van Rossumab2490a1992-06-03 17:07:23 +000077 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000078 case T_LONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +000079 v = PyInt_FromLong(*(long*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000080 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000081 case T_ULONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +000082 v = PyLong_FromDouble((double)
Guido van Rossumab2490a1992-06-03 17:07:23 +000083 *(unsigned long*)addr);
84 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000085 case T_FLOAT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000086 v = PyFloat_FromDouble((double)*(float*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000087 break;
88 case T_DOUBLE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000089 v = PyFloat_FromDouble(*(double*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000090 break;
91 case T_STRING:
92 if (*(char**)addr == NULL) {
Guido van Rossum79f25d91997-04-29 20:08:16 +000093 Py_INCREF(Py_None);
94 v = Py_None;
Guido van Rossum3f5da241990-12-20 15:06:42 +000095 }
96 else
Guido van Rossum79f25d91997-04-29 20:08:16 +000097 v = PyString_FromString(*(char**)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000098 break;
Jack Jansen599f0d11994-12-14 13:04:05 +000099 case T_STRING_INPLACE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000100 v = PyString_FromString((char*)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000101 break;
102#ifdef macintosh
103 case T_PSTRING:
104 if (*(char**)addr == NULL) {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000105 Py_INCREF(Py_None);
106 v = Py_None;
Jack Jansen599f0d11994-12-14 13:04:05 +0000107 }
108 else
Guido van Rossum79f25d91997-04-29 20:08:16 +0000109 v = PyString_FromStringAndSize(
110 (*(char**)addr)+1,
111 **(unsigned char**)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000112 break;
113 case T_PSTRING_INPLACE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000114 v = PyString_FromStringAndSize(
115 ((char*)addr)+1,
116 *(unsigned char*)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000117 break;
118#endif /* macintosh */
Guido van Rossumab2490a1992-06-03 17:07:23 +0000119 case T_CHAR:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000120 v = PyString_FromStringAndSize((char*)addr, 1);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000121 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000122 case T_OBJECT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000123 v = *(PyObject **)addr;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000124 if (v == NULL)
Guido van Rossum79f25d91997-04-29 20:08:16 +0000125 v = Py_None;
126 Py_INCREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000127 break;
128 default:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000129 PyErr_SetString(PyExc_SystemError,
130 "bad memberlist type");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000131 v = NULL;
132 }
133 return v;
134 }
135 }
136
Guido van Rossum79f25d91997-04-29 20:08:16 +0000137 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000138 return NULL;
139}
140
141int
Guido van Rossum79f25d91997-04-29 20:08:16 +0000142PyMember_Set(addr, mlist, name, v)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143 char *addr;
144 struct memberlist *mlist;
145 char *name;
Guido van Rossum79f25d91997-04-29 20:08:16 +0000146 PyObject *v;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000147{
148 struct memberlist *l;
Guido van Rossumadf0e431998-05-20 22:25:32 +0000149 PyObject *oldv;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000150
151 for (l = mlist; l->name != NULL; l++) {
152 if (strcmp(l->name, name) == 0) {
Jack Jansen599f0d11994-12-14 13:04:05 +0000153#ifdef macintosh
Guido van Rossum79f25d91997-04-29 20:08:16 +0000154 if (l->readonly || l->type == T_STRING ||
155 l->type == T_PSTRING)
156 {
Jack Jansen599f0d11994-12-14 13:04:05 +0000157#else
158 if (l->readonly || l->type == T_STRING ) {
159#endif /* macintosh */
Guido van Rossum79f25d91997-04-29 20:08:16 +0000160 PyErr_SetString(PyExc_TypeError,
161 "readonly attribute");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000162 return -1;
163 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000164 if (v == NULL && l->type != T_OBJECT) {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000165 PyErr_SetString(PyExc_TypeError,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000166 "can't delete numeric/char attribute");
167 return -1;
168 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000169 addr += l->offset;
170 switch (l->type) {
Guido van Rossumab2490a1992-06-03 17:07:23 +0000171 case T_BYTE:
172 case T_UBYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000173 if (!PyInt_Check(v)) {
174 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000175 return -1;
176 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000177 *(char*)addr = (char) PyInt_AsLong(v);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000178 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000179 case T_SHORT:
Guido van Rossumab2490a1992-06-03 17:07:23 +0000180 case T_USHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000181 if (!PyInt_Check(v)) {
182 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000183 return -1;
184 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000185 *(short*)addr = (short) PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000186 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000187 case T_UINT:
Guido van Rossum3f5da241990-12-20 15:06:42 +0000188 case T_INT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000189 if (!PyInt_Check(v)) {
190 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000191 return -1;
192 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000193 *(int*)addr = (int) PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000194 break;
195 case T_LONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000196 if (!PyInt_Check(v)) {
197 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000198 return -1;
199 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000200 *(long*)addr = PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000201 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000202 case T_ULONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000203 if (PyInt_Check(v))
204 *(long*)addr = PyInt_AsLong(v);
205 else if (PyLong_Check(v))
206 *(long*)addr = PyLong_AsLong(v);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000207 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000208 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000209 return -1;
210 }
211 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000212 case T_FLOAT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000213 if (PyInt_Check(v))
Guido van Rossum644a12b1997-04-09 19:24:53 +0000214 *(float*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000215 (float) PyInt_AsLong(v);
216 else if (PyFloat_Check(v))
217 *(float*)addr =
218 (float) PyFloat_AsDouble(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000219 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000220 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000221 return -1;
222 }
223 break;
224 case T_DOUBLE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000225 if (PyInt_Check(v))
Guido van Rossum644a12b1997-04-09 19:24:53 +0000226 *(double*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000227 (double) PyInt_AsLong(v);
228 else if (PyFloat_Check(v))
229 *(double*)addr = PyFloat_AsDouble(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000230 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000231 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000232 return -1;
233 }
234 break;
235 case T_OBJECT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000236 Py_XINCREF(v);
Guido van Rossumadf0e431998-05-20 22:25:32 +0000237 oldv = *(PyObject **)addr;
Guido van Rossum79f25d91997-04-29 20:08:16 +0000238 *(PyObject **)addr = v;
Guido van Rossumadf0e431998-05-20 22:25:32 +0000239 Py_XDECREF(oldv);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000240 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000241 case T_CHAR:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000242 if (PyString_Check(v) &&
243 PyString_Size(v) == 1) {
Guido van Rossumab2490a1992-06-03 17:07:23 +0000244 *(char*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000245 PyString_AsString(v)[0];
Guido van Rossumab2490a1992-06-03 17:07:23 +0000246 }
247 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000248 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000249 return -1;
250 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000251 default:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000252 PyErr_SetString(PyExc_SystemError,
253 "bad memberlist type");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000254 return -1;
255 }
256 return 0;
257 }
258 }
259
Guido van Rossum79f25d91997-04-29 20:08:16 +0000260 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum73531a31990-12-20 23:12:40 +0000261 return -1;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000262}