1/* Copyright (c) 1996,97 by Lele Gaifax.  All Rights Reserved
2 * With various updates by Ronald Oussoren and others ((C) 2002, 2003)
3 *
4 * This software may be used and distributed freely for any purpose
5 * provided that this notice is included unchanged on any and all
6 * copies. The author does not warrant or guarantee this software in
7 * any way.
8 *
9 * This file is part of the PyObjC package.
10 *
11 * Created Mon Oct 28 12:38:18 1996.
12 *
13 */
14
15#include "pyobjc.h"
16
17int PyObjCPointer_RaiseException = 0;
18
19static void
20PyObjCPointer_dealloc (PyObject* _self)
21{
22	PyObjCPointer* self = (PyObjCPointer*)_self;
23	Py_DECREF (self->type);
24	PyObject_Free((PyObject*)self);
25}
26
27PyDoc_STRVAR(PyObjCPointer_unpack_doc,
28	"Unpack the pointed value accordingly to its type.\n"
29        "obj.unpack() -> value");
30static PyObject *
31PyObjCPointer_unpack (PyObject* _self)
32{
33	PyObjCPointer* self = (PyObjCPointer*)_self;
34
35	if (self->ptr) {
36		const char *type = PyBytes_AS_STRING (self->type);
37
38		if (*type == _C_VOID) {
39			PyErr_SetString (PyObjCExc_Error,
40				"Cannot dereference a pointer to void");
41			return NULL;
42		} else {
43			return pythonify_c_value (type, self->ptr);
44		}
45        } else {
46		Py_INCREF (Py_None);
47		return Py_None;
48        }
49}
50
51static PyMethodDef PyObjCPointer_methods[] =
52{
53	{
54		"unpack",
55		(PyCFunction)PyObjCPointer_unpack,
56		METH_NOARGS,
57		PyObjCPointer_unpack_doc
58	},
59	{ 0, 0, 0, 0 }
60};
61
62static PyMemberDef PyObjCPointer_members[] = {
63	{
64		"type",
65		T_OBJECT,
66		offsetof(PyObjCPointer, type),
67		READONLY,
68		NULL
69	},
70	{
71		"pointerAsInteger",
72		T_INT,
73		offsetof(PyObjCPointer, ptr),
74		READONLY,
75		NULL
76	},
77	{ 0, 0, 0, 0, 0 }
78};
79
80PyTypeObject PyObjCPointer_Type =
81{
82	PyVarObject_HEAD_INIT(&PyType_Type, 0)
83	"PyObjCPointer",			/* tp_name */
84	sizeof (PyObjCPointer),			/* tp_basicsize */
85	sizeof (char),				/* tp_itemsize */
86
87	/* methods */
88	PyObjCPointer_dealloc,			/* tp_dealloc */
89	0,					/* tp_print */
90	0,					/* tp_getattr */
91	0,					/* tp_setattr */
92	0,					/* tp_compare */
93	0,					/* tp_repr */
94	0,					/* tp_as_number */
95	0,					/* tp_as_sequence */
96	0,					/* tp_as_mapping */
97	0,					/* tp_hash */
98	0,					/* tp_call */
99	0,					/* tp_str */
100	0,					/* tp_getattro */
101	0,					/* tp_setattro */
102	0,					/* tp_as_buffer */
103	Py_TPFLAGS_DEFAULT,			/* tp_flags */
104	"Wrapper around a Objective-C Pointer",	/* tp_doc */
105	0,					/* tp_traverse */
106	0,					/* tp_clear */
107	0,					/* tp_richcompare */
108	0,					/* tp_weaklistoffset */
109	0,					/* tp_iter */
110	0,					/* tp_iternext */
111	PyObjCPointer_methods,			/* tp_methods */
112	PyObjCPointer_members,			/* tp_members */
113	0,					/* tp_getset */
114	0,					/* tp_base */
115	0,					/* tp_dict */
116	0,					/* tp_descr_get */
117	0,					/* tp_descr_set */
118	0,					/* tp_dictoffset */
119	0,					/* tp_init */
120	0,					/* tp_alloc */
121	0,					/* tp_new */
122	0,					/* tp_free */
123	0,					/* tp_is_gc */
124	0,					/* tp_bases */
125	0,					/* tp_mro */
126	0,					/* tp_cache */
127	0,					/* tp_subclasses */
128	0,					/* tp_weaklist */
129	0					/* tp_del */
130#if PY_VERSION_HEX >= 0x02060000
131	, 0                                     /* tp_version_tag */
132#endif
133
134};
135
136PyObjCPointer *
137PyObjCPointer_New(void *p, const char *t)
138{
139	Py_ssize_t size = PyObjCRT_SizeOfType (t);
140	const char *typeend = PyObjCRT_SkipTypeSpec (t);
141	PyObjCPointer *self;
142
143	if (PyObjCPointer_RaiseException) {
144		PyErr_Format(PyObjCExc_UnknownPointerError,
145			"pointer of type %s", t);
146		return NULL;
147	}
148	NSLog(@"PyObjCPointer created: at %p of type %s", p, t);
149
150	if (size == -1) {
151		return NULL;
152	}
153	if (typeend == NULL) {
154		return NULL;
155	}
156
157	self = PyObject_NEW_VAR (PyObjCPointer, &PyObjCPointer_Type, size);
158	if (self == NULL) {
159		return NULL;
160	}
161
162	self->type = PyBytes_FromStringAndSize ((char *) t, typeend-t);
163
164	if (size && p) {
165		memcpy ((self->ptr = self->contents), p, size);
166	} else {
167		self->ptr = p;
168	}
169
170	return self;
171}
172