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