Bump version to 0.9.1.
[python/dscho.git] / Python / structmember.c
blob891ffa0c6d887ec2f9e9d568b0b6d7da68556eb7
1 /***********************************************************
2 Copyright (c) 2000, BeOpen.com.
3 Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4 Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5 All rights reserved.
7 See the file "Misc/COPYRIGHT" for information on usage and
8 redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9 ******************************************************************/
11 /* Map C struct members to Python object attributes */
13 #include "Python.h"
15 #include "structmember.h"
17 static PyObject *
18 listmembers(struct memberlist *mlist)
20 int i, n;
21 PyObject *v;
22 for (n = 0; mlist[n].name != NULL; n++)
24 v = PyList_New(n);
25 if (v != NULL) {
26 for (i = 0; i < n; i++)
27 PyList_SetItem(v, i,
28 PyString_FromString(mlist[i].name));
29 if (PyErr_Occurred()) {
30 Py_DECREF(v);
31 v = NULL;
33 else {
34 PyList_Sort(v);
37 return v;
40 PyObject *
41 PyMember_Get(char *addr, struct memberlist *mlist, char *name)
43 struct memberlist *l;
45 if (strcmp(name, "__members__") == 0)
46 return listmembers(mlist);
47 for (l = mlist; l->name != NULL; l++) {
48 if (strcmp(l->name, name) == 0) {
49 PyObject *v;
50 addr += l->offset;
51 switch (l->type) {
52 case T_BYTE:
53 v = PyInt_FromLong((long)
54 (((*(char*)addr & 0xff)
55 ^ 0x80) - 0x80));
56 break;
57 case T_UBYTE:
58 v = PyInt_FromLong((long) *(char*)addr & 0xff);
59 break;
60 case T_SHORT:
61 v = PyInt_FromLong((long) *(short*)addr);
62 break;
63 case T_USHORT:
64 v = PyInt_FromLong((long)
65 *(unsigned short*)addr);
66 break;
67 case T_INT:
68 v = PyInt_FromLong((long) *(int*)addr);
69 break;
70 case T_UINT:
71 v = PyInt_FromLong((long)
72 *(unsigned int*)addr);
73 break;
74 case T_LONG:
75 v = PyInt_FromLong(*(long*)addr);
76 break;
77 case T_ULONG:
78 v = PyLong_FromDouble((double)
79 *(unsigned long*)addr);
80 break;
81 case T_FLOAT:
82 v = PyFloat_FromDouble((double)*(float*)addr);
83 break;
84 case T_DOUBLE:
85 v = PyFloat_FromDouble(*(double*)addr);
86 break;
87 case T_STRING:
88 if (*(char**)addr == NULL) {
89 Py_INCREF(Py_None);
90 v = Py_None;
92 else
93 v = PyString_FromString(*(char**)addr);
94 break;
95 case T_STRING_INPLACE:
96 v = PyString_FromString((char*)addr);
97 break;
98 #ifdef macintosh
99 case T_PSTRING:
100 if (*(char**)addr == NULL) {
101 Py_INCREF(Py_None);
102 v = Py_None;
104 else
105 v = PyString_FromStringAndSize(
106 (*(char**)addr)+1,
107 **(unsigned char**)addr);
108 break;
109 case T_PSTRING_INPLACE:
110 v = PyString_FromStringAndSize(
111 ((char*)addr)+1,
112 *(unsigned char*)addr);
113 break;
114 #endif /* macintosh */
115 case T_CHAR:
116 v = PyString_FromStringAndSize((char*)addr, 1);
117 break;
118 case T_OBJECT:
119 v = *(PyObject **)addr;
120 if (v == NULL)
121 v = Py_None;
122 Py_INCREF(v);
123 break;
124 default:
125 PyErr_SetString(PyExc_SystemError,
126 "bad memberlist type");
127 v = NULL;
129 return v;
133 PyErr_SetString(PyExc_AttributeError, name);
134 return NULL;
138 PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
140 struct memberlist *l;
141 PyObject *oldv;
143 for (l = mlist; l->name != NULL; l++) {
144 if (strcmp(l->name, name) == 0) {
145 #ifdef macintosh
146 if (l->readonly || l->type == T_STRING ||
147 l->type == T_PSTRING)
149 #else
150 if (l->readonly || l->type == T_STRING ) {
151 #endif /* macintosh */
152 PyErr_SetString(PyExc_TypeError,
153 "readonly attribute");
154 return -1;
156 if (v == NULL && l->type != T_OBJECT) {
157 PyErr_SetString(PyExc_TypeError,
158 "can't delete numeric/char attribute");
159 return -1;
161 addr += l->offset;
162 switch (l->type) {
163 case T_BYTE:
164 case T_UBYTE:
165 if (!PyInt_Check(v)) {
166 PyErr_BadArgument();
167 return -1;
169 *(char*)addr = (char) PyInt_AsLong(v);
170 break;
171 case T_SHORT:
172 case T_USHORT:
173 if (!PyInt_Check(v)) {
174 PyErr_BadArgument();
175 return -1;
177 *(short*)addr = (short) PyInt_AsLong(v);
178 break;
179 case T_UINT:
180 case T_INT:
181 if (!PyInt_Check(v)) {
182 PyErr_BadArgument();
183 return -1;
185 *(int*)addr = (int) PyInt_AsLong(v);
186 break;
187 case T_LONG:
188 if (!PyInt_Check(v)) {
189 PyErr_BadArgument();
190 return -1;
192 *(long*)addr = PyInt_AsLong(v);
193 break;
194 case T_ULONG:
195 if (PyInt_Check(v))
196 *(long*)addr = PyInt_AsLong(v);
197 else if (PyLong_Check(v))
198 *(long*)addr = PyLong_AsLong(v);
199 else {
200 PyErr_BadArgument();
201 return -1;
203 break;
204 case T_FLOAT:
205 if (PyInt_Check(v))
206 *(float*)addr =
207 (float) PyInt_AsLong(v);
208 else if (PyFloat_Check(v))
209 *(float*)addr =
210 (float) PyFloat_AsDouble(v);
211 else {
212 PyErr_BadArgument();
213 return -1;
215 break;
216 case T_DOUBLE:
217 if (PyInt_Check(v))
218 *(double*)addr =
219 (double) PyInt_AsLong(v);
220 else if (PyFloat_Check(v))
221 *(double*)addr = PyFloat_AsDouble(v);
222 else {
223 PyErr_BadArgument();
224 return -1;
226 break;
227 case T_OBJECT:
228 Py_XINCREF(v);
229 oldv = *(PyObject **)addr;
230 *(PyObject **)addr = v;
231 Py_XDECREF(oldv);
232 break;
233 case T_CHAR:
234 if (PyString_Check(v) &&
235 PyString_Size(v) == 1) {
236 *(char*)addr =
237 PyString_AsString(v)[0];
239 else {
240 PyErr_BadArgument();
241 return -1;
243 default:
244 PyErr_SetString(PyExc_SystemError,
245 "bad memberlist type");
246 return -1;
248 return 0;
252 PyErr_SetString(PyExc_AttributeError, name);
253 return -1;