1#include "pyobjc.h" 2#import "OC_PythonData.h" 3 4@implementation OC_PythonData 5 6+ (OC_PythonData*)dataWithPythonObject:(PyObject*)v 7{ 8 OC_PythonData* res; 9 10 res = [[OC_PythonData alloc] initWithPythonObject:v]; 11 [res autorelease]; 12 return res; 13} 14 15 16- (OC_PythonData*)initWithPythonObject:(PyObject*)v 17{ 18 self = [super init]; 19 if (unlikely(self == nil)) return nil; 20 21 if (unlikely(PyObject_AsReadBuffer(v, &buffer, &buffer_len) == -1)) { 22 [super dealloc]; 23 return nil; 24 } 25 Py_INCREF(v); 26 Py_XDECREF(value); 27 value = v; 28 return self; 29} 30 31-(PyObject*)__pyobjc_PythonObject__ 32{ 33 Py_INCREF(value); 34 return value; 35} 36 37-(PyObject*)__pyobjc_PythonTransient__:(int*)cookie 38{ 39 *cookie = 0; 40 Py_INCREF(value); 41 return value; 42} 43 44-(BOOL)supportsWeakPointers { return YES; } 45 46-(oneway void)release 47{ 48 /* See comment in OC_PythonUnicode */ 49 PyObjC_BEGIN_WITH_GIL 50 [super release]; 51 PyObjC_END_WITH_GIL 52} 53 54 55 56-(void)dealloc 57{ 58 PyObjC_BEGIN_WITH_GIL 59 PyObjC_UnregisterObjCProxy(value, self); 60 Py_XDECREF(value); 61 62 PyObjC_END_WITH_GIL 63 64 [super dealloc]; 65} 66 67-(NSUInteger)length 68{ 69 NSUInteger rval; 70 71 PyObjC_BEGIN_WITH_GIL 72 if (unlikely(PyObject_AsReadBuffer(value, &buffer, &buffer_len) == -1)) { 73 PyErr_Clear(); 74 rval = 0; 75 } else { 76 if ((NSUInteger)buffer_len > NSUIntegerMax) { 77 rval = NSUIntegerMax; 78 } else { 79 rval = buffer_len; 80 } 81 } 82 PyObjC_END_WITH_GIL 83 return rval; 84} 85 86-(const void *)bytes 87{ 88 const void *rval; 89 PyObjC_BEGIN_WITH_GIL 90 if (unlikely(PyObject_AsReadBuffer(value, &buffer, &buffer_len) == -1)) { 91 PyErr_Clear(); 92 rval = NULL; 93 } 94 rval = buffer; 95 PyObjC_END_WITH_GIL 96 return rval; 97} 98 99-(Class)classForCoder 100{ 101 return [OC_PythonData class]; 102} 103 104 105-(void)encodeWithCoder:(NSCoder*)coder 106{ 107 108 PyObjC_BEGIN_WITH_GIL 109 if (PyBytes_CheckExact(value)) { 110 if (unlikely(PyObject_AsReadBuffer(value, &buffer, &buffer_len) == -1)) { 111 PyObjC_GIL_FORWARD_EXC(); 112 } 113 114 115 if ([coder allowsKeyedCoding]) { 116 [coder encodeInt32:1 forKey:@"pytype"]; 117 [coder encodeBytes:buffer length:buffer_len forKey: @"pybytes"]; 118 119 } else { 120 int v = 1; 121 [coder encodeValueOfObjCType:@encode(int) at:&v]; 122 [coder encodeBytes:buffer length:buffer_len]; 123 } 124 125 } else { 126 if ([coder allowsKeyedCoding]) { 127 [coder encodeInt32:2 forKey:@"pytype"]; 128 } else { 129 int v = 2; 130 [coder encodeValueOfObjCType:@encode(int) at:&v]; 131 } 132 133 PyObjC_encodeWithCoder(value, coder); 134 } 135 PyObjC_END_WITH_GIL 136} 137 138/* 139 * Helper method for initWithCoder, needed to deal with 140 * recursive objects (e.g. o.value = o) 141 */ 142-(void)pyobjcSetValue:(NSObject*)other 143{ 144 PyObjC_BEGIN_WITH_GIL 145 PyObject* v = PyObjC_IdToPython(other); 146 Py_XDECREF(value); 147 value = v; 148 PyObjC_END_WITH_GIL 149} 150 151- (id)initWithCoder:(NSCoder*)coder 152{ 153 int v; 154 155 if ([coder allowsKeyedCoding]) { 156 157 v = [coder decodeInt32ForKey:@"pytype"]; 158 } else { 159 [coder decodeValueOfObjCType:@encode(int) at:&v]; 160 } 161 if (v == 1) { 162 self = [super init]; 163 if (unlikely(self == nil)) return nil; 164 165 const void *bytes; 166 NSUInteger length; 167 168 if ([coder allowsKeyedCoding]) { 169 bytes = [coder decodeBytesForKey:@"pybytes" returnedLength:&length]; 170 } else { 171 bytes = [coder decodeBytesWithReturnedLength:&length]; 172 } 173 PyObjC_BEGIN_WITH_GIL 174 value = PyBytes_FromStringAndSize(bytes, length); 175 if (value == NULL) { 176 [super dealloc]; 177 PyObjC_GIL_FORWARD_EXC(); 178 } 179 PyObjC_END_WITH_GIL; 180 return self; 181 182 } else if (v == 2) { 183 184 if (PyObjC_Decoder != NULL) { 185 PyObjC_BEGIN_WITH_GIL 186 PyObject* cdr = PyObjC_IdToPython(coder); 187 if (cdr == NULL) { 188 PyObjC_GIL_FORWARD_EXC(); 189 } 190 191 PyObject* setValue; 192 PyObject* selfAsPython = PyObjCObject_New(self, 0, YES); 193 setValue = PyObject_GetAttrString(selfAsPython, "pyobjcSetValue_"); 194 195 PyObject* v2 = PyObject_CallFunction(PyObjC_Decoder, "OO", cdr, setValue); 196 Py_DECREF(cdr); 197 Py_DECREF(setValue); 198 Py_DECREF(selfAsPython); 199 200 if (v2 == NULL) { 201 PyObjC_GIL_FORWARD_EXC(); 202 } 203 204 Py_XDECREF(value); 205 value = v2; 206 207 NSObject* proxy = PyObjC_FindObjCProxy(value); 208 if (proxy == NULL) { 209 PyObjC_RegisterObjCProxy(value, self); 210 } else { 211 [self release]; 212 [proxy retain]; 213 self = (OC_PythonData*)proxy; 214 } 215 216 217 PyObjC_END_WITH_GIL 218 219 return self; 220 221 } else { 222 [NSException raise:NSInvalidArgumentException 223 format:@"decoding Python objects is not supported"]; 224 return nil; 225 226 } 227 228 } else { 229 [NSException raise:NSInvalidArgumentException 230 format:@"encoding Python objects is not supported"]; 231 } 232 return self; 233} 234 235 236@end /* implementation OC_PythonData */ 237