1/*
2 * These NSData methods don't "fit" the metadata model.
3 * -bytes
4 * -mutableBytes
5 */
6#include <Python.h>
7#include "pyobjc-api.h"
8
9#include <Foundation/Foundation.h>
10
11
12static PyObject* call_NSData_bytes(
13	PyObject* method, PyObject* self, PyObject* arguments)
14{
15	const void* bytes;
16	NSUInteger    bytes_len;
17	PyObject* result;
18	struct objc_super super;
19
20	if (!PyArg_ParseTuple(arguments, "")) {
21		return NULL;
22	}
23
24	PyObjC_DURING
25		PyObjC_InitSuper(&super,
26			PyObjCSelector_GetClass(method),
27			PyObjCObject_GetObject(self));
28
29		bytes = objc_msgSendSuper(&super,
30				PyObjCSelector_GetSelector(method));
31		bytes_len = (NSUInteger) objc_msgSendSuper(&super, @selector(length));
32
33
34	PyObjC_HANDLER
35		PyObjCErr_FromObjC(localException);
36		result = NULL;
37		bytes = NULL;
38		bytes_len = 0;
39	PyObjC_ENDHANDLER
40
41	if (bytes == NULL && PyErr_Occurred()) return NULL;
42
43	result = PyBuffer_FromMemory((void*)bytes, bytes_len);
44
45	return result;
46}
47
48static void
49imp_NSData_bytes(
50	void* cif __attribute__((__unused__)),
51	void* resp,
52	void** args,
53	void* callable)
54{
55	id self = *(id*)args[0];
56	//SEL _meth = *(SEL*)args[1];
57	void** pretval = (void**)resp;
58
59	PyObject* result;
60	PyObject* arglist = NULL;
61	PyObject* pyself = NULL;
62	int cookie = 0;
63
64	PyGILState_STATE state = PyGILState_Ensure();
65
66	arglist = PyTuple_New(1);
67	if (arglist == NULL) goto error;
68
69	pyself = PyObjCObject_NewTransient(self, &cookie);
70	if (pyself == NULL) goto error;
71	PyTuple_SetItem(arglist, 0, pyself);
72	Py_INCREF(pyself);
73
74	result = PyObject_Call((PyObject*)callable, arglist, NULL);
75	Py_DECREF(arglist); arglist = NULL;
76	PyObjCObject_ReleaseTransient(pyself, cookie); pyself = NULL;
77	if (result == NULL) goto error;
78
79	if (result == Py_None) {
80		*pretval = NULL;
81		Py_DECREF(result);
82		PyGILState_Release(state);
83		return;
84	}
85
86	if (PyBuffer_Check(result)) {
87		/* XXX: Is this correct?? */
88		const void *p;
89		Py_ssize_t len;
90		if (PyObject_AsReadBuffer(result, &p, &len) == -1) {
91			goto error;
92		}
93		Py_DECREF(result);
94		*pretval =  (void *)p;
95		PyGILState_Release(state);
96		return;
97	} else if (PyString_Check(result)) {
98		/* XXX: Is this correct */
99		void* p;
100
101		p = PyString_AsString(result);
102		*pretval = (void*)p;
103		PyGILState_Release(state);
104		return;
105	}
106
107	PyErr_SetString(PyExc_ValueError, "No idea what to do with result.");
108	goto error;
109
110error:
111	Py_XDECREF(arglist);
112	if (pyself) {
113		PyObjCObject_ReleaseTransient(pyself, cookie);
114	}
115	PyObjCErr_ToObjCWithGILState(&state);
116	*pretval = NULL;
117}
118
119
120static PyObject*
121call_NSMutableData_mutableBytes(
122	PyObject* method, PyObject* self, PyObject* arguments)
123{
124	void*     bytes;
125	NSUInteger  bytes_len;
126	PyObject* result;
127	struct objc_super super;
128
129	if (!PyArg_ParseTuple(arguments, "")) {
130		return NULL;
131	}
132
133	PyObjC_DURING
134		PyObjC_InitSuper(&super,
135			PyObjCSelector_GetClass(method),
136			PyObjCObject_GetObject(self));
137
138		bytes = objc_msgSendSuper(&super,
139				PyObjCSelector_GetSelector(method));
140		bytes_len = (NSUInteger) objc_msgSendSuper(&super, @selector(length));
141
142	PyObjC_HANDLER
143		PyObjCErr_FromObjC(localException);
144		result = NULL;
145		bytes = NULL;
146		bytes_len = 0;
147	PyObjC_ENDHANDLER
148
149	if (bytes == NULL && PyErr_Occurred()) return NULL;
150
151	result = PyBuffer_FromReadWriteMemory((void*)bytes, bytes_len);
152
153	return result;
154}
155
156static void
157imp_NSMutableData_mutableBytes(
158	void* cif __attribute__((__unused__)),
159	void* resp,
160	void** args,
161	void* callable)
162{
163	id self = *(id*)args[0];
164	//SEL _meth = *(SEL*)args[1];
165	void** pretval = (void**)resp;
166	PyObject* result;
167	PyObject* arglist = NULL;
168	PyObject* pyself = NULL;
169	int cookie = 0;
170
171	PyGILState_STATE state = PyGILState_Ensure();
172
173	arglist = PyTuple_New(1);
174	if (arglist == NULL) goto error;
175
176	pyself = PyObjCObject_NewTransient(self, &cookie);
177	if (pyself == NULL) goto error;
178	PyTuple_SetItem(arglist, 0, pyself);
179	Py_INCREF(pyself);
180
181	result = PyObject_Call((PyObject*)callable, arglist, NULL);
182	Py_DECREF(arglist); arglist = NULL;
183	PyObjCObject_ReleaseTransient(pyself, cookie); pyself = NULL;
184	if (result == NULL) goto error;
185
186	if (result == Py_None) {
187		Py_DECREF(result);
188		goto error;
189	}
190
191	if (result == Py_None) {
192		*pretval = NULL;
193		Py_DECREF(result);
194		PyGILState_Release(state);
195		return;
196	}
197
198	if (PyBuffer_Check(result)) {
199		/* XXX: Is this correct? */
200		void *p;
201		Py_ssize_t len;
202		if (PyObject_AsWriteBuffer(result, &p, &len) == -1) goto error;
203		Py_DECREF(result);
204		*pretval = (void *)p;
205		PyGILState_Release(state);
206		return;
207	}
208
209	PyErr_SetString(PyExc_ValueError, "No idea what to do with result.");
210	PyObjCErr_ToObjCWithGILState(&state);
211	*pretval = NULL;
212	return;
213
214error:
215	Py_XDECREF(arglist);
216	if (pyself) {
217		PyObjCObject_ReleaseTransient(pyself, cookie);
218	}
219	*pretval = NULL;
220	PyObjCErr_ToObjCWithGILState(&state);
221}
222
223static PyMethodDef _methods[] = {
224	        { 0, 0, 0, 0 } /* sentinel */
225};
226
227void
228init_data(void)
229{
230	PyObject* m = Py_InitModule4("_data", _methods, "", NULL, PYTHON_API_VERSION);
231	if (m == NULL) return;
232	if (PyObjC_ImportAPI(m) < 0) return;
233
234	Class classNSData = objc_lookUpClass("NSData");
235	Class classNSMutableData = objc_lookUpClass("NSMutableData");
236
237	if (classNSData != NULL) {
238
239		if (PyObjC_RegisterMethodMapping(classNSData,
240				 @selector(bytes),
241				 call_NSData_bytes,
242				 imp_NSData_bytes) < 0 ) {
243			return;
244		}
245
246	}
247
248	if (classNSMutableData != NULL) {
249
250		if (PyObjC_RegisterMethodMapping(classNSMutableData,
251				@selector(mutableBytes),
252				call_NSMutableData_mutableBytes,
253				imp_NSMutableData_mutableBytes) < 0 ) {
254			return;
255		}
256	}
257
258
259	return;
260}
261