| 
									
										
										
										
											1991-02-19 12:39:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | /* Map C struct members to Python object attributes */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "structmember.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2000-07-22 18:47:25 +00:00
										 |  |  | listmembers(struct memberlist *mlist) | 
					
						
							| 
									
										
										
										
											1991-10-20 20:24:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i, n; | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | 	PyObject *v; | 
					
						
							| 
									
										
										
										
											1991-10-20 20:24:14 +00:00
										 |  |  | 	for (n = 0; mlist[n].name != NULL; n++) | 
					
						
							|  |  |  | 		; | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | 	v = PyList_New(n); | 
					
						
							| 
									
										
										
										
											1991-10-20 20:24:14 +00:00
										 |  |  | 	if (v != NULL) { | 
					
						
							|  |  |  | 		for (i = 0; i < n; i++) | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | 			PyList_SetItem(v, i, | 
					
						
							|  |  |  | 				       PyString_FromString(mlist[i].name)); | 
					
						
							|  |  |  | 		if (PyErr_Occurred()) { | 
					
						
							|  |  |  | 			Py_DECREF(v); | 
					
						
							| 
									
										
										
										
											1991-10-20 20:24:14 +00:00
										 |  |  | 			v = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | 			PyList_Sort(v); | 
					
						
							| 
									
										
										
										
											1991-10-20 20:24:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2005-12-24 06:03:06 +00:00
										 |  |  | PyMember_Get(const char *addr, struct memberlist *mlist, const char *name) | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct memberlist *l; | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1991-10-20 20:24:14 +00:00
										 |  |  | 	if (strcmp(name, "__members__") == 0) | 
					
						
							|  |  |  | 		return listmembers(mlist); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	for (l = mlist; l->name != NULL; l++) { | 
					
						
							|  |  |  | 		if (strcmp(l->name, name) == 0) { | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 			PyMemberDef copy; | 
					
						
							|  |  |  | 			copy.name = l->name; | 
					
						
							|  |  |  | 			copy.type = l->type; | 
					
						
							|  |  |  | 			copy.offset = l->offset; | 
					
						
							|  |  |  | 			copy.flags = l->flags; | 
					
						
							|  |  |  | 			copy.doc = NULL; | 
					
						
							|  |  |  | 			return PyMember_GetOne(addr, ©); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | 	PyErr_SetString(PyExc_AttributeError, name); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2005-12-24 06:03:06 +00:00
										 |  |  | PyMember_GetOne(const char *addr, PyMemberDef *l) | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *v; | 
					
						
							|  |  |  | 	if ((l->flags & READ_RESTRICTED) && | 
					
						
							|  |  |  | 	    PyEval_GetRestricted()) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	addr += l->offset; | 
					
						
							|  |  |  | 	switch (l->type) { | 
					
						
							|  |  |  | 	case T_BYTE: | 
					
						
							|  |  |  | 		v = PyInt_FromLong( | 
					
						
							|  |  |  | 			(long) (((*(char*)addr & 0xff) ^ 0x80) - 0x80)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_UBYTE: | 
					
						
							|  |  |  | 		v = PyInt_FromLong((long) *(char*)addr & 0xff); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_SHORT: | 
					
						
							|  |  |  | 		v = PyInt_FromLong((long) *(short*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_USHORT: | 
					
						
							|  |  |  | 		v = PyInt_FromLong((long) *(unsigned short*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_INT: | 
					
						
							|  |  |  | 		v = PyInt_FromLong((long) *(int*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_UINT: | 
					
						
							|  |  |  | 		v = PyInt_FromLong((long) *(unsigned int*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_LONG: | 
					
						
							|  |  |  | 		v = PyInt_FromLong(*(long*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_ULONG: | 
					
						
							|  |  |  | 		v = PyLong_FromDouble((double) *(unsigned long*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_FLOAT: | 
					
						
							|  |  |  | 		v = PyFloat_FromDouble((double)*(float*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_DOUBLE: | 
					
						
							|  |  |  | 		v = PyFloat_FromDouble(*(double*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_STRING: | 
					
						
							|  |  |  | 		if (*(char**)addr == NULL) { | 
					
						
							|  |  |  | 			Py_INCREF(Py_None); | 
					
						
							|  |  |  | 			v = Py_None; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			v = PyString_FromString(*(char**)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_STRING_INPLACE: | 
					
						
							|  |  |  | 		v = PyString_FromString((char*)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_CHAR: | 
					
						
							|  |  |  | 		v = PyString_FromStringAndSize((char*)addr, 1); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_OBJECT: | 
					
						
							|  |  |  | 		v = *(PyObject **)addr; | 
					
						
							|  |  |  | 		if (v == NULL) | 
					
						
							|  |  |  | 			v = Py_None; | 
					
						
							|  |  |  | 		Py_INCREF(v); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2001-12-04 16:23:42 +00:00
										 |  |  | 	case T_OBJECT_EX: | 
					
						
							|  |  |  | 		v = *(PyObject **)addr; | 
					
						
							|  |  |  | 		if (v == NULL) | 
					
						
							|  |  |  | 			PyErr_SetString(PyExc_AttributeError, l->name); | 
					
						
							|  |  |  | 		Py_XINCREF(v); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-03-03 23:00:26 +00:00
										 |  |  | #ifdef HAVE_LONG_LONG
 | 
					
						
							|  |  |  | 	case T_LONGLONG: | 
					
						
							|  |  |  | 		v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_ULONGLONG: | 
					
						
							|  |  |  | 		v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | #endif /* HAVE_LONG_LONG */
 | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); | 
					
						
							|  |  |  | 		v = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2005-12-24 06:03:06 +00:00
										 |  |  | PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v) | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct memberlist *l; | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	for (l = mlist; l->name != NULL; l++) { | 
					
						
							|  |  |  | 		if (strcmp(l->name, name) == 0) { | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 			PyMemberDef copy; | 
					
						
							|  |  |  | 			copy.name = l->name; | 
					
						
							|  |  |  | 			copy.type = l->type; | 
					
						
							|  |  |  | 			copy.offset = l->offset; | 
					
						
							|  |  |  | 			copy.flags = l->flags; | 
					
						
							|  |  |  | 			copy.doc = NULL; | 
					
						
							|  |  |  | 			return PyMember_SetOne(addr, ©, v); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-04-29 20:08:16 +00:00
										 |  |  | 	PyErr_SetString(PyExc_AttributeError, name); | 
					
						
							| 
									
										
										
										
											1990-12-20 23:12:40 +00:00
										 |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *oldv; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-20 01:44:59 +00:00
										 |  |  | 	if ((l->flags & READONLY) || l->type == T_STRING) | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, "readonly attribute"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((l->flags & WRITE_RESTRICTED) && PyEval_GetRestricted()) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-12-04 16:23:42 +00:00
										 |  |  | 	if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) { | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"can't delete numeric/char attribute"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	addr += l->offset; | 
					
						
							|  |  |  | 	switch (l->type) { | 
					
						
							|  |  |  | 	case T_BYTE: | 
					
						
							|  |  |  | 	case T_UBYTE: | 
					
						
							|  |  |  | 		if (!PyInt_Check(v)) { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*(char*)addr = (char) PyInt_AsLong(v); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_SHORT: | 
					
						
							|  |  |  | 	case T_USHORT: | 
					
						
							|  |  |  | 		if (!PyInt_Check(v)) { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*(short*)addr = (short) PyInt_AsLong(v); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_UINT: | 
					
						
							|  |  |  | 	case T_INT: | 
					
						
							|  |  |  | 		if (!PyInt_Check(v)) { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*(int*)addr = (int) PyInt_AsLong(v); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_LONG: | 
					
						
							|  |  |  | 		if (!PyInt_Check(v)) { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*(long*)addr = PyInt_AsLong(v); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_ULONG: | 
					
						
							|  |  |  | 		if (PyInt_Check(v)) | 
					
						
							|  |  |  | 			*(long*)addr = PyInt_AsLong(v); | 
					
						
							|  |  |  | 		else if (PyLong_Check(v)) | 
					
						
							|  |  |  | 			*(long*)addr = PyLong_AsLong(v); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_FLOAT: | 
					
						
							|  |  |  | 		if (PyInt_Check(v)) | 
					
						
							|  |  |  | 			*(float*)addr = | 
					
						
							|  |  |  | 				(float) PyInt_AsLong(v); | 
					
						
							|  |  |  | 		else if (PyFloat_Check(v)) | 
					
						
							|  |  |  | 			*(float*)addr = | 
					
						
							|  |  |  | 				(float) PyFloat_AsDouble(v); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_DOUBLE: | 
					
						
							|  |  |  | 		if (PyInt_Check(v)) | 
					
						
							|  |  |  | 			*(double*)addr = (double) PyInt_AsLong(v); | 
					
						
							|  |  |  | 		else if (PyFloat_Check(v)) | 
					
						
							|  |  |  | 			*(double*)addr = PyFloat_AsDouble(v); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_OBJECT: | 
					
						
							| 
									
										
										
										
											2001-12-04 16:23:42 +00:00
										 |  |  | 	case T_OBJECT_EX: | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 		Py_XINCREF(v); | 
					
						
							|  |  |  | 		oldv = *(PyObject **)addr; | 
					
						
							|  |  |  | 		*(PyObject **)addr = v; | 
					
						
							|  |  |  | 		Py_XDECREF(oldv); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case T_CHAR: | 
					
						
							|  |  |  | 		if (PyString_Check(v) && PyString_Size(v) == 1) { | 
					
						
							|  |  |  | 			*(char*)addr = PyString_AsString(v)[0]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-03-03 23:00:26 +00:00
										 |  |  | #ifdef HAVE_LONG_LONG
 | 
					
						
							|  |  |  | 	case T_LONGLONG: | 
					
						
							|  |  |  | 		if (!PyLong_Check(v)) { | 
					
						
							|  |  |  | 			PyErr_BadArgument(); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  |                         *(PY_LONG_LONG*)addr = PyLong_AsLongLong(v); | 
					
						
							|  |  |  |                         if ((*addr == -1) && PyErr_Occurred()) { | 
					
						
							|  |  |  |                                 return -1; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 	case T_ULONGLONG: | 
					
						
							|  |  |  |                 if (!PyLong_Check(v)) { | 
					
						
							|  |  |  |                         PyErr_BadArgument(); | 
					
						
							|  |  |  |                         return -1; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                         *(unsigned PY_LONG_LONG*)addr = PyLong_AsUnsignedLongLong(v); | 
					
						
							|  |  |  |                         if ((*addr == -1) && PyErr_Occurred()) { | 
					
						
							|  |  |  |                                 return -1; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | #endif /* HAVE_LONG_LONG */
 | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2001-10-16 16:51:56 +00:00
										 |  |  | 		PyErr_Format(PyExc_SystemError, | 
					
						
							|  |  |  | 			     "bad memberdescr type for %s", l->name); | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } |