blob: a64b4eb3232b977a59223a7892847aa46b79b21d [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
5 All Rights Reserved
6
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007Copyright (c) 2000, BeOpen.com.
8Copyright (c) 1995-2000, Corporation for National Research Initiatives.
9Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
10All rights reserved.
Guido van Rossumf70e43a1991-02-19 12:39:46 +000011
Guido van Rossumfd71b9e2000-06-30 23:50:40 +000012See the file "Misc/COPYRIGHT" for information on usage and
13redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossumf70e43a1991-02-19 12:39:46 +000014
15******************************************************************/
16
Guido van Rossum3f5da241990-12-20 15:06:42 +000017/* Map C struct members to Python object attributes */
18
Guido van Rossum79f25d91997-04-29 20:08:16 +000019#include "Python.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000020
21#include "structmember.h"
22
Guido van Rossum79f25d91997-04-29 20:08:16 +000023static PyObject *
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000024listmembers(mlist)
25 struct memberlist *mlist;
26{
27 int i, n;
Guido van Rossum79f25d91997-04-29 20:08:16 +000028 PyObject *v;
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000029 for (n = 0; mlist[n].name != NULL; n++)
30 ;
Guido van Rossum79f25d91997-04-29 20:08:16 +000031 v = PyList_New(n);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000032 if (v != NULL) {
33 for (i = 0; i < n; i++)
Guido van Rossum79f25d91997-04-29 20:08:16 +000034 PyList_SetItem(v, i,
35 PyString_FromString(mlist[i].name));
36 if (PyErr_Occurred()) {
37 Py_DECREF(v);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000038 v = NULL;
39 }
40 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +000041 PyList_Sort(v);
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000042 }
43 }
44 return v;
45}
46
Guido van Rossum79f25d91997-04-29 20:08:16 +000047PyObject *
48PyMember_Get(addr, mlist, name)
Guido van Rossum3f5da241990-12-20 15:06:42 +000049 char *addr;
50 struct memberlist *mlist;
51 char *name;
52{
53 struct memberlist *l;
54
Guido van Rossum2f1d87e1991-10-20 20:24:14 +000055 if (strcmp(name, "__members__") == 0)
56 return listmembers(mlist);
Guido van Rossum3f5da241990-12-20 15:06:42 +000057 for (l = mlist; l->name != NULL; l++) {
58 if (strcmp(l->name, name) == 0) {
Guido van Rossum79f25d91997-04-29 20:08:16 +000059 PyObject *v;
Guido van Rossum3f5da241990-12-20 15:06:42 +000060 addr += l->offset;
61 switch (l->type) {
Guido van Rossumab2490a1992-06-03 17:07:23 +000062 case T_BYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000063 v = PyInt_FromLong((long)
Guido van Rossumab2490a1992-06-03 17:07:23 +000064 (((*(char*)addr & 0xff)
65 ^ 0x80) - 0x80));
66 break;
67 case T_UBYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000068 v = PyInt_FromLong((long) *(char*)addr & 0xff);
Guido van Rossumab2490a1992-06-03 17:07:23 +000069 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000070 case T_SHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000071 v = PyInt_FromLong((long) *(short*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000072 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000073 case T_USHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000074 v = PyInt_FromLong((long)
Guido van Rossumab2490a1992-06-03 17:07:23 +000075 *(unsigned short*)addr);
76 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000077 case T_INT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000078 v = PyInt_FromLong((long) *(int*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000079 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000080 case T_UINT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000081 v = PyInt_FromLong((long)
82 *(unsigned int*)addr);
Guido van Rossumab2490a1992-06-03 17:07:23 +000083 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000084 case T_LONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +000085 v = PyInt_FromLong(*(long*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000086 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +000087 case T_ULONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +000088 v = PyLong_FromDouble((double)
Guido van Rossumab2490a1992-06-03 17:07:23 +000089 *(unsigned long*)addr);
90 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +000091 case T_FLOAT:
Guido van Rossum79f25d91997-04-29 20:08:16 +000092 v = PyFloat_FromDouble((double)*(float*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000093 break;
94 case T_DOUBLE:
Guido van Rossum79f25d91997-04-29 20:08:16 +000095 v = PyFloat_FromDouble(*(double*)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +000096 break;
97 case T_STRING:
98 if (*(char**)addr == NULL) {
Guido van Rossum79f25d91997-04-29 20:08:16 +000099 Py_INCREF(Py_None);
100 v = Py_None;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000101 }
102 else
Guido van Rossum79f25d91997-04-29 20:08:16 +0000103 v = PyString_FromString(*(char**)addr);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000104 break;
Jack Jansen599f0d11994-12-14 13:04:05 +0000105 case T_STRING_INPLACE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000106 v = PyString_FromString((char*)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000107 break;
108#ifdef macintosh
109 case T_PSTRING:
110 if (*(char**)addr == NULL) {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000111 Py_INCREF(Py_None);
112 v = Py_None;
Jack Jansen599f0d11994-12-14 13:04:05 +0000113 }
114 else
Guido van Rossum79f25d91997-04-29 20:08:16 +0000115 v = PyString_FromStringAndSize(
116 (*(char**)addr)+1,
117 **(unsigned char**)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000118 break;
119 case T_PSTRING_INPLACE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000120 v = PyString_FromStringAndSize(
121 ((char*)addr)+1,
122 *(unsigned char*)addr);
Jack Jansen599f0d11994-12-14 13:04:05 +0000123 break;
124#endif /* macintosh */
Guido van Rossumab2490a1992-06-03 17:07:23 +0000125 case T_CHAR:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000126 v = PyString_FromStringAndSize((char*)addr, 1);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000127 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000128 case T_OBJECT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000129 v = *(PyObject **)addr;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000130 if (v == NULL)
Guido van Rossum79f25d91997-04-29 20:08:16 +0000131 v = Py_None;
132 Py_INCREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000133 break;
134 default:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000135 PyErr_SetString(PyExc_SystemError,
136 "bad memberlist type");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000137 v = NULL;
138 }
139 return v;
140 }
141 }
142
Guido van Rossum79f25d91997-04-29 20:08:16 +0000143 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000144 return NULL;
145}
146
147int
Guido van Rossum79f25d91997-04-29 20:08:16 +0000148PyMember_Set(addr, mlist, name, v)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000149 char *addr;
150 struct memberlist *mlist;
151 char *name;
Guido van Rossum79f25d91997-04-29 20:08:16 +0000152 PyObject *v;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000153{
154 struct memberlist *l;
Guido van Rossumadf0e431998-05-20 22:25:32 +0000155 PyObject *oldv;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000156
157 for (l = mlist; l->name != NULL; l++) {
158 if (strcmp(l->name, name) == 0) {
Jack Jansen599f0d11994-12-14 13:04:05 +0000159#ifdef macintosh
Guido van Rossum79f25d91997-04-29 20:08:16 +0000160 if (l->readonly || l->type == T_STRING ||
161 l->type == T_PSTRING)
162 {
Jack Jansen599f0d11994-12-14 13:04:05 +0000163#else
164 if (l->readonly || l->type == T_STRING ) {
165#endif /* macintosh */
Guido van Rossum79f25d91997-04-29 20:08:16 +0000166 PyErr_SetString(PyExc_TypeError,
167 "readonly attribute");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000168 return -1;
169 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000170 if (v == NULL && l->type != T_OBJECT) {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000171 PyErr_SetString(PyExc_TypeError,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000172 "can't delete numeric/char attribute");
173 return -1;
174 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000175 addr += l->offset;
176 switch (l->type) {
Guido van Rossumab2490a1992-06-03 17:07:23 +0000177 case T_BYTE:
178 case T_UBYTE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000179 if (!PyInt_Check(v)) {
180 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000181 return -1;
182 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000183 *(char*)addr = (char) PyInt_AsLong(v);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000184 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000185 case T_SHORT:
Guido van Rossumab2490a1992-06-03 17:07:23 +0000186 case T_USHORT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000187 if (!PyInt_Check(v)) {
188 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000189 return -1;
190 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000191 *(short*)addr = (short) PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000192 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000193 case T_UINT:
Guido van Rossum3f5da241990-12-20 15:06:42 +0000194 case T_INT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000195 if (!PyInt_Check(v)) {
196 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000197 return -1;
198 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000199 *(int*)addr = (int) PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000200 break;
201 case T_LONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000202 if (!PyInt_Check(v)) {
203 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000204 return -1;
205 }
Guido van Rossum79f25d91997-04-29 20:08:16 +0000206 *(long*)addr = PyInt_AsLong(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000207 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000208 case T_ULONG:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000209 if (PyInt_Check(v))
210 *(long*)addr = PyInt_AsLong(v);
211 else if (PyLong_Check(v))
212 *(long*)addr = PyLong_AsLong(v);
Guido van Rossumab2490a1992-06-03 17:07:23 +0000213 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000214 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000215 return -1;
216 }
217 break;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000218 case T_FLOAT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000219 if (PyInt_Check(v))
Guido van Rossum644a12b1997-04-09 19:24:53 +0000220 *(float*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000221 (float) PyInt_AsLong(v);
222 else if (PyFloat_Check(v))
223 *(float*)addr =
224 (float) PyFloat_AsDouble(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000225 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000226 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000227 return -1;
228 }
229 break;
230 case T_DOUBLE:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000231 if (PyInt_Check(v))
Guido van Rossum644a12b1997-04-09 19:24:53 +0000232 *(double*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000233 (double) PyInt_AsLong(v);
234 else if (PyFloat_Check(v))
235 *(double*)addr = PyFloat_AsDouble(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000236 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000237 PyErr_BadArgument();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000238 return -1;
239 }
240 break;
241 case T_OBJECT:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000242 Py_XINCREF(v);
Guido van Rossumadf0e431998-05-20 22:25:32 +0000243 oldv = *(PyObject **)addr;
Guido van Rossum79f25d91997-04-29 20:08:16 +0000244 *(PyObject **)addr = v;
Guido van Rossumadf0e431998-05-20 22:25:32 +0000245 Py_XDECREF(oldv);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000246 break;
Guido van Rossumab2490a1992-06-03 17:07:23 +0000247 case T_CHAR:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000248 if (PyString_Check(v) &&
249 PyString_Size(v) == 1) {
Guido van Rossumab2490a1992-06-03 17:07:23 +0000250 *(char*)addr =
Guido van Rossum79f25d91997-04-29 20:08:16 +0000251 PyString_AsString(v)[0];
Guido van Rossumab2490a1992-06-03 17:07:23 +0000252 }
253 else {
Guido van Rossum79f25d91997-04-29 20:08:16 +0000254 PyErr_BadArgument();
Guido van Rossumab2490a1992-06-03 17:07:23 +0000255 return -1;
256 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000257 default:
Guido van Rossum79f25d91997-04-29 20:08:16 +0000258 PyErr_SetString(PyExc_SystemError,
259 "bad memberlist type");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000260 return -1;
261 }
262 return 0;
263 }
264 }
265
Guido van Rossum79f25d91997-04-29 20:08:16 +0000266 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum73531a31990-12-20 23:12:40 +0000267 return -1;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000268}