structmember.c 6.46 KB
Newer Older
1
/***********************************************************
2 3
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
4 5 6

                        All Rights Reserved

7 8
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
9
provided that the above copyright notice appear in all copies and that
10
both that copyright notice and this permission notice appear in
11
supporting documentation, and that the names of Stichting Mathematisch
12 13 14 15
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
16

17 18 19 20 21 22 23 24 25 26 27 28
While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
29 30 31

******************************************************************/

Guido van Rossum's avatar
Guido van Rossum committed
32 33
/* Map C struct members to Python object attributes */

34
#include "Python.h"
Guido van Rossum's avatar
Guido van Rossum committed
35 36 37

#include "structmember.h"

38
static PyObject *
39 40 41 42
listmembers(mlist)
	struct memberlist *mlist;
{
	int i, n;
43
	PyObject *v;
44 45
	for (n = 0; mlist[n].name != NULL; n++)
		;
46
	v = PyList_New(n);
47 48
	if (v != NULL) {
		for (i = 0; i < n; i++)
49 50 51 52
			PyList_SetItem(v, i,
				       PyString_FromString(mlist[i].name));
		if (PyErr_Occurred()) {
			Py_DECREF(v);
53 54 55
			v = NULL;
		}
		else {
56
			PyList_Sort(v);
57 58 59 60 61
		}
	}
	return v;
}

62 63
PyObject *
PyMember_Get(addr, mlist, name)
Guido van Rossum's avatar
Guido van Rossum committed
64 65 66 67 68 69
	char *addr;
	struct memberlist *mlist;
	char *name;
{
	struct memberlist *l;
	
70 71
	if (strcmp(name, "__members__") == 0)
		return listmembers(mlist);
Guido van Rossum's avatar
Guido van Rossum committed
72 73
	for (l = mlist; l->name != NULL; l++) {
		if (strcmp(l->name, name) == 0) {
74
			PyObject *v;
Guido van Rossum's avatar
Guido van Rossum committed
75 76
			addr += l->offset;
			switch (l->type) {
77
			case T_BYTE:
78
				v = PyInt_FromLong((long)
79 80 81 82
						 (((*(char*)addr & 0xff)
						   ^ 0x80) - 0x80));
				break;
			case T_UBYTE:
83
				v = PyInt_FromLong((long) *(char*)addr & 0xff);
84
				break;
Guido van Rossum's avatar
Guido van Rossum committed
85
			case T_SHORT:
86
				v = PyInt_FromLong((long) *(short*)addr);
Guido van Rossum's avatar
Guido van Rossum committed
87
				break;
88
			case T_USHORT:
89
				v = PyInt_FromLong((long)
90 91
						 *(unsigned short*)addr);
				break;
Guido van Rossum's avatar
Guido van Rossum committed
92
			case T_INT:
93
				v = PyInt_FromLong((long) *(int*)addr);
Guido van Rossum's avatar
Guido van Rossum committed
94
				break;
95
			case T_UINT:
96 97
				v = PyInt_FromLong((long)
						   *(unsigned int*)addr);
98
				break;
Guido van Rossum's avatar
Guido van Rossum committed
99
			case T_LONG:
100
				v = PyInt_FromLong(*(long*)addr);
Guido van Rossum's avatar
Guido van Rossum committed
101
				break;
102
			case T_ULONG:
103
				v = PyLong_FromDouble((double)
104 105
						   *(unsigned long*)addr);
				break;
Guido van Rossum's avatar
Guido van Rossum committed
106
			case T_FLOAT:
107
				v = PyFloat_FromDouble((double)*(float*)addr);
Guido van Rossum's avatar
Guido van Rossum committed
108 109
				break;
			case T_DOUBLE:
110
				v = PyFloat_FromDouble(*(double*)addr);
Guido van Rossum's avatar
Guido van Rossum committed
111 112 113
				break;
			case T_STRING:
				if (*(char**)addr == NULL) {
114 115
					Py_INCREF(Py_None);
					v = Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
116 117
				}
				else
118
					v = PyString_FromString(*(char**)addr);
Guido van Rossum's avatar
Guido van Rossum committed
119
				break;
120
			case T_STRING_INPLACE:
121
				v = PyString_FromString((char*)addr);
122 123 124 125
				break;
#ifdef macintosh
			case T_PSTRING:
				if (*(char**)addr == NULL) {
126 127
					Py_INCREF(Py_None);
					v = Py_None;
128 129
				}
				else
130 131 132
					v = PyString_FromStringAndSize(
						(*(char**)addr)+1,
						**(unsigned char**)addr);
133 134
				break;
			case T_PSTRING_INPLACE:
135 136 137
				v = PyString_FromStringAndSize(
					((char*)addr)+1,
					*(unsigned char*)addr);
138 139
				break;
#endif /* macintosh */
140
			case T_CHAR:
141
				v = PyString_FromStringAndSize((char*)addr, 1);
142
				break;
Guido van Rossum's avatar
Guido van Rossum committed
143
			case T_OBJECT:
144
				v = *(PyObject **)addr;
Guido van Rossum's avatar
Guido van Rossum committed
145
				if (v == NULL)
146 147
					v = Py_None;
				Py_INCREF(v);
Guido van Rossum's avatar
Guido van Rossum committed
148 149
				break;
			default:
150 151
				PyErr_SetString(PyExc_SystemError,
						"bad memberlist type");
Guido van Rossum's avatar
Guido van Rossum committed
152 153 154 155 156 157
				v = NULL;
			}
			return v;
		}
	}
	
158
	PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum's avatar
Guido van Rossum committed
159 160 161 162
	return NULL;
}

int
163
PyMember_Set(addr, mlist, name, v)
Guido van Rossum's avatar
Guido van Rossum committed
164 165 166
	char *addr;
	struct memberlist *mlist;
	char *name;
167
	PyObject *v;
Guido van Rossum's avatar
Guido van Rossum committed
168 169 170 171 172
{
	struct memberlist *l;
	
	for (l = mlist; l->name != NULL; l++) {
		if (strcmp(l->name, name) == 0) {
173
#ifdef macintosh
174 175 176
			if (l->readonly || l->type == T_STRING ||
			    l->type == T_PSTRING)
			{
177 178 179
#else
			if (l->readonly || l->type == T_STRING ) {
#endif /* macintosh */
180 181
				PyErr_SetString(PyExc_TypeError,
						"readonly attribute");
Guido van Rossum's avatar
Guido van Rossum committed
182 183
				return -1;
			}
184
			if (v == NULL && l->type != T_OBJECT) {
185
				PyErr_SetString(PyExc_TypeError,
186 187 188
				  "can't delete numeric/char attribute");
				return -1;
			}
Guido van Rossum's avatar
Guido van Rossum committed
189 190
			addr += l->offset;
			switch (l->type) {
191 192
			case T_BYTE:
			case T_UBYTE:
193 194
				if (!PyInt_Check(v)) {
					PyErr_BadArgument();
195 196
					return -1;
				}
197
				*(char*)addr = (char) PyInt_AsLong(v);
198
				break;
Guido van Rossum's avatar
Guido van Rossum committed
199
			case T_SHORT:
200
			case T_USHORT:
201 202
				if (!PyInt_Check(v)) {
					PyErr_BadArgument();
Guido van Rossum's avatar
Guido van Rossum committed
203 204
					return -1;
				}
205
				*(short*)addr = (short) PyInt_AsLong(v);
Guido van Rossum's avatar
Guido van Rossum committed
206
				break;
207
			case T_UINT:
Guido van Rossum's avatar
Guido van Rossum committed
208
			case T_INT:
209 210
				if (!PyInt_Check(v)) {
					PyErr_BadArgument();
Guido van Rossum's avatar
Guido van Rossum committed
211 212
					return -1;
				}
213
				*(int*)addr = (int) PyInt_AsLong(v);
Guido van Rossum's avatar
Guido van Rossum committed
214 215
				break;
			case T_LONG:
216 217
				if (!PyInt_Check(v)) {
					PyErr_BadArgument();
Guido van Rossum's avatar
Guido van Rossum committed
218 219
					return -1;
				}
220
				*(long*)addr = PyInt_AsLong(v);
Guido van Rossum's avatar
Guido van Rossum committed
221
				break;
222
			case T_ULONG:
223 224 225 226
				if (PyInt_Check(v))
					*(long*)addr = PyInt_AsLong(v);
				else if (PyLong_Check(v))
					*(long*)addr = PyLong_AsLong(v);
227
				else {
228
					PyErr_BadArgument();
229 230 231
					return -1;
				}
				break;
Guido van Rossum's avatar
Guido van Rossum committed
232
			case T_FLOAT:
233
				if (PyInt_Check(v))
234
					*(float*)addr =
235 236 237 238
						(float) PyInt_AsLong(v);
				else if (PyFloat_Check(v))
					*(float*)addr =
						(float) PyFloat_AsDouble(v);
Guido van Rossum's avatar
Guido van Rossum committed
239
				else {
240
					PyErr_BadArgument();
Guido van Rossum's avatar
Guido van Rossum committed
241 242 243 244
					return -1;
				}
				break;
			case T_DOUBLE:
245
				if (PyInt_Check(v))
246
					*(double*)addr =
247 248 249
						(double) PyInt_AsLong(v);
				else if (PyFloat_Check(v))
					*(double*)addr = PyFloat_AsDouble(v);
Guido van Rossum's avatar
Guido van Rossum committed
250
				else {
251
					PyErr_BadArgument();
Guido van Rossum's avatar
Guido van Rossum committed
252 253 254 255
					return -1;
				}
				break;
			case T_OBJECT:
256 257 258
				Py_XDECREF(*(PyObject **)addr);
				Py_XINCREF(v);
				*(PyObject **)addr = v;
Guido van Rossum's avatar
Guido van Rossum committed
259
				break;
260
			case T_CHAR:
261 262
				if (PyString_Check(v) &&
				    PyString_Size(v) == 1) {
263
					*(char*)addr =
264
						PyString_AsString(v)[0];
265 266
				}
				else {
267
					PyErr_BadArgument();
268 269
					return -1;
				}
Guido van Rossum's avatar
Guido van Rossum committed
270
			default:
271 272
				PyErr_SetString(PyExc_SystemError,
						"bad memberlist type");
Guido van Rossum's avatar
Guido van Rossum committed
273 274 275 276 277 278
				return -1;
			}
			return 0;
		}
	}
	
279
	PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum's avatar
Guido van Rossum committed
280
	return -1;
Guido van Rossum's avatar
Guido van Rossum committed
281
}