Updated for 2.1b2 distribution.
[python/dscho.git] / Python / structmember.c
blobe155a6b49f8c6f60ecaf7bfb9a4ba2a68112356e
2 /* Map C struct members to Python object attributes */
4 #include "Python.h"
6 #include "structmember.h"
8 static PyObject *
9 listmembers(struct memberlist *mlist)
11 int i, n;
12 PyObject *v;
13 for (n = 0; mlist[n].name != NULL; n++)
15 v = PyList_New(n);
16 if (v != NULL) {
17 for (i = 0; i < n; i++)
18 PyList_SetItem(v, i,
19 PyString_FromString(mlist[i].name));
20 if (PyErr_Occurred()) {
21 Py_DECREF(v);
22 v = NULL;
24 else {
25 PyList_Sort(v);
28 return v;
31 PyObject *
32 PyMember_Get(char *addr, struct memberlist *mlist, char *name)
34 struct memberlist *l;
36 if (strcmp(name, "__members__") == 0)
37 return listmembers(mlist);
38 for (l = mlist; l->name != NULL; l++) {
39 if (strcmp(l->name, name) == 0) {
40 PyObject *v;
41 addr += l->offset;
42 switch (l->type) {
43 case T_BYTE:
44 v = PyInt_FromLong((long)
45 (((*(char*)addr & 0xff)
46 ^ 0x80) - 0x80));
47 break;
48 case T_UBYTE:
49 v = PyInt_FromLong((long) *(char*)addr & 0xff);
50 break;
51 case T_SHORT:
52 v = PyInt_FromLong((long) *(short*)addr);
53 break;
54 case T_USHORT:
55 v = PyInt_FromLong((long)
56 *(unsigned short*)addr);
57 break;
58 case T_INT:
59 v = PyInt_FromLong((long) *(int*)addr);
60 break;
61 case T_UINT:
62 v = PyInt_FromLong((long)
63 *(unsigned int*)addr);
64 break;
65 case T_LONG:
66 v = PyInt_FromLong(*(long*)addr);
67 break;
68 case T_ULONG:
69 v = PyLong_FromDouble((double)
70 *(unsigned long*)addr);
71 break;
72 case T_FLOAT:
73 v = PyFloat_FromDouble((double)*(float*)addr);
74 break;
75 case T_DOUBLE:
76 v = PyFloat_FromDouble(*(double*)addr);
77 break;
78 case T_STRING:
79 if (*(char**)addr == NULL) {
80 Py_INCREF(Py_None);
81 v = Py_None;
83 else
84 v = PyString_FromString(*(char**)addr);
85 break;
86 case T_STRING_INPLACE:
87 v = PyString_FromString((char*)addr);
88 break;
89 #ifdef macintosh
90 case T_PSTRING:
91 if (*(char**)addr == NULL) {
92 Py_INCREF(Py_None);
93 v = Py_None;
95 else
96 v = PyString_FromStringAndSize(
97 (*(char**)addr)+1,
98 **(unsigned char**)addr);
99 break;
100 case T_PSTRING_INPLACE:
101 v = PyString_FromStringAndSize(
102 ((char*)addr)+1,
103 *(unsigned char*)addr);
104 break;
105 #endif /* macintosh */
106 case T_CHAR:
107 v = PyString_FromStringAndSize((char*)addr, 1);
108 break;
109 case T_OBJECT:
110 v = *(PyObject **)addr;
111 if (v == NULL)
112 v = Py_None;
113 Py_INCREF(v);
114 break;
115 default:
116 PyErr_SetString(PyExc_SystemError,
117 "bad memberlist type");
118 v = NULL;
120 return v;
124 PyErr_SetString(PyExc_AttributeError, name);
125 return NULL;
129 PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
131 struct memberlist *l;
132 PyObject *oldv;
134 for (l = mlist; l->name != NULL; l++) {
135 if (strcmp(l->name, name) == 0) {
136 #ifdef macintosh
137 if (l->readonly || l->type == T_STRING ||
138 l->type == T_PSTRING)
140 #else
141 if (l->readonly || l->type == T_STRING ) {
142 #endif /* macintosh */
143 PyErr_SetString(PyExc_TypeError,
144 "readonly attribute");
145 return -1;
147 if (v == NULL && l->type != T_OBJECT) {
148 PyErr_SetString(PyExc_TypeError,
149 "can't delete numeric/char attribute");
150 return -1;
152 addr += l->offset;
153 switch (l->type) {
154 case T_BYTE:
155 case T_UBYTE:
156 if (!PyInt_Check(v)) {
157 PyErr_BadArgument();
158 return -1;
160 *(char*)addr = (char) PyInt_AsLong(v);
161 break;
162 case T_SHORT:
163 case T_USHORT:
164 if (!PyInt_Check(v)) {
165 PyErr_BadArgument();
166 return -1;
168 *(short*)addr = (short) PyInt_AsLong(v);
169 break;
170 case T_UINT:
171 case T_INT:
172 if (!PyInt_Check(v)) {
173 PyErr_BadArgument();
174 return -1;
176 *(int*)addr = (int) PyInt_AsLong(v);
177 break;
178 case T_LONG:
179 if (!PyInt_Check(v)) {
180 PyErr_BadArgument();
181 return -1;
183 *(long*)addr = PyInt_AsLong(v);
184 break;
185 case T_ULONG:
186 if (PyInt_Check(v))
187 *(long*)addr = PyInt_AsLong(v);
188 else if (PyLong_Check(v))
189 *(long*)addr = PyLong_AsLong(v);
190 else {
191 PyErr_BadArgument();
192 return -1;
194 break;
195 case T_FLOAT:
196 if (PyInt_Check(v))
197 *(float*)addr =
198 (float) PyInt_AsLong(v);
199 else if (PyFloat_Check(v))
200 *(float*)addr =
201 (float) PyFloat_AsDouble(v);
202 else {
203 PyErr_BadArgument();
204 return -1;
206 break;
207 case T_DOUBLE:
208 if (PyInt_Check(v))
209 *(double*)addr =
210 (double) PyInt_AsLong(v);
211 else if (PyFloat_Check(v))
212 *(double*)addr = PyFloat_AsDouble(v);
213 else {
214 PyErr_BadArgument();
215 return -1;
217 break;
218 case T_OBJECT:
219 Py_XINCREF(v);
220 oldv = *(PyObject **)addr;
221 *(PyObject **)addr = v;
222 Py_XDECREF(oldv);
223 break;
224 case T_CHAR:
225 if (PyString_Check(v) &&
226 PyString_Size(v) == 1) {
227 *(char*)addr =
228 PyString_AsString(v)[0];
230 else {
231 PyErr_BadArgument();
232 return -1;
234 break;
235 default:
236 PyErr_SetString(PyExc_SystemError,
237 "bad memberlist type");
238 return -1;
240 return 0;
244 PyErr_SetString(PyExc_AttributeError, name);
245 return -1;