PageRenderTime 95ms CodeModel.GetById 52ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/Mac/Modules/cf/pycfbridge.c

http://unladen-swallow.googlecode.com/
C | 303 lines | 263 code | 28 blank | 12 comment | 78 complexity | 46a8cd4e91920186b684548c50c9917e MD5 | raw file
  1/*
  2** Convert objects from Python to CoreFoundation and vice-versa.
  3*/
  4
  5#include <CoreServices/CoreServices.h>
  6
  7#include "Python.h"
  8#include "pymactoolbox.h"
  9#include "pycfbridge.h"
 10
 11
 12/* ---------------------------------------- */
 13/* CoreFoundation objects to Python objects */
 14/* ---------------------------------------- */
 15
 16PyObject *
 17PyCF_CF2Python(CFTypeRef src) {
 18	CFTypeID typeid;
 19	
 20	if( src == NULL ) {
 21		Py_INCREF(Py_None);
 22		return Py_None;
 23	}
 24	typeid = CFGetTypeID(src);
 25	if (typeid == CFArrayGetTypeID())
 26		return PyCF_CF2Python_sequence((CFArrayRef)src);
 27	if (typeid == CFDictionaryGetTypeID())
 28		return PyCF_CF2Python_mapping((CFDictionaryRef)src);
 29	return PyCF_CF2Python_simple(src);
 30}
 31
 32PyObject *
 33PyCF_CF2Python_sequence(CFArrayRef src) {
 34	int size = CFArrayGetCount(src);
 35	PyObject *rv;
 36	CFTypeRef item_cf;
 37	PyObject *item_py = NULL;
 38	int i;
 39	
 40	if ( (rv=PyList_New(size)) == NULL )
 41		return NULL;
 42	for(i=0; i<size; i++) {
 43		item_cf = CFArrayGetValueAtIndex(src, i);
 44		if (item_cf == NULL ) goto err;
 45		item_py = PyCF_CF2Python(item_cf);
 46		if (item_py == NULL ) goto err;
 47		if (PyList_SetItem(rv, i, item_py) < 0) goto err;
 48		item_py = NULL;
 49	}
 50	return rv;
 51err:
 52	Py_XDECREF(item_py);
 53	Py_DECREF(rv);
 54	return NULL;
 55}
 56
 57PyObject *
 58PyCF_CF2Python_mapping(CFTypeRef src) {
 59	int size = CFDictionaryGetCount(src);
 60	PyObject *rv = NULL;
 61	CFTypeRef *allkeys = NULL, *allvalues = NULL;
 62	CFTypeRef key_cf, value_cf;
 63	PyObject *key_py = NULL, *value_py = NULL;
 64	int i;
 65	
 66	allkeys = malloc(size*sizeof(CFTypeRef *));
 67	if (allkeys == NULL) {
 68		PyErr_NoMemory();
 69		goto err;
 70	}
 71	allvalues = malloc(size*sizeof(CFTypeRef *));
 72	if (allvalues == NULL) {
 73		PyErr_NoMemory();
 74		goto err;
 75	}
 76	if ( (rv=PyDict_New()) == NULL ) goto err;
 77	CFDictionaryGetKeysAndValues(src, allkeys, allvalues);
 78	for(i=0; i<size; i++) {
 79		key_cf = allkeys[i];
 80		value_cf = allvalues[i];
 81		key_py = PyCF_CF2Python(key_cf);
 82		if (key_py == NULL ) goto err;
 83		value_py = PyCF_CF2Python(value_cf);
 84		if (value_py == NULL ) goto err;
 85		if (PyDict_SetItem(rv, key_py, value_py) < 0) goto err;
 86		key_py = NULL;
 87		value_py = NULL;
 88	}
 89	return rv;
 90err:
 91	Py_XDECREF(key_py);
 92	Py_XDECREF(value_py);
 93	Py_XDECREF(rv);
 94	free(allkeys);
 95	free(allvalues);
 96	return NULL;
 97}
 98
 99PyObject *
100PyCF_CF2Python_simple(CFTypeRef src) {
101	CFTypeID typeid;
102	
103	typeid = CFGetTypeID(src);
104	if (typeid == CFStringGetTypeID())
105		return PyCF_CF2Python_string((CFStringRef)src);
106	if (typeid == CFBooleanGetTypeID())
107		return PyBool_FromLong((long)CFBooleanGetValue(src));
108	if (typeid == CFNumberGetTypeID()) {
109		if (CFNumberIsFloatType(src)) {
110			double d;
111			CFNumberGetValue(src, kCFNumberDoubleType, &d);
112			return PyFloat_FromDouble(d);
113		} else {
114			long l;
115			if (!CFNumberGetValue(src, kCFNumberLongType, &l))
116				/* XXXX Out of range! */;
117			return PyInt_FromLong(l);
118		}
119	}
120	/* XXXX Should return as CFTypeRef, really... */
121	PyMac_Error(resNotFound);
122	return NULL;
123}
124
125/* Unsure - Return unicode or 8 bit strings? */
126PyObject *
127PyCF_CF2Python_string(CFStringRef src) {
128	int size = CFStringGetLength(src)+1;
129	Py_UNICODE *data = malloc(size*sizeof(Py_UNICODE));
130	CFRange range;
131	PyObject *rv;
132
133	range.location = 0;
134	range.length = size;
135	if( data == NULL ) return PyErr_NoMemory();
136	CFStringGetCharacters(src, range, data);
137	rv = (PyObject *)PyUnicode_FromUnicode(data, size-1);
138	free(data);
139	return rv;
140}
141
142/* ---------------------------------------- */
143/* Python objects to CoreFoundation objects */
144/* ---------------------------------------- */
145
146int
147PyCF_Python2CF(PyObject *src, CFTypeRef *dst) {
148
149	if (PyString_Check(src) || PyUnicode_Check(src))
150		return PyCF_Python2CF_simple(src, dst);
151	if (PySequence_Check(src))
152		return PyCF_Python2CF_sequence(src, (CFArrayRef *)dst);
153	if (PyMapping_Check(src))
154		return PyCF_Python2CF_mapping(src, (CFDictionaryRef *)dst);
155	return PyCF_Python2CF_simple(src, dst);
156}
157
158int
159PyCF_Python2CF_sequence(PyObject *src, CFArrayRef *dst) {
160	CFMutableArrayRef rv = NULL;
161	CFTypeRef item_cf = NULL;
162	PyObject *item_py = NULL;
163	int size, i;
164	
165	if( !PySequence_Check(src) ) {
166		PyErr_Format(PyExc_TypeError,
167			"Cannot convert %.500s objects to CFArray",
168			src->ob_type->tp_name);
169		return 0;
170	}
171	size = PySequence_Size(src);
172	rv = CFArrayCreateMutable((CFAllocatorRef)NULL, size, &kCFTypeArrayCallBacks);
173	if (rv == NULL) {
174		PyMac_Error(resNotFound); 
175		goto err;
176	}
177
178	for( i=0; i<size; i++) {
179		item_py = PySequence_GetItem(src, i);
180		if (item_py == NULL) goto err;
181		if ( !PyCF_Python2CF(item_py, &item_cf)) goto err;
182		Py_DECREF(item_py);
183		CFArraySetValueAtIndex(rv, i, item_cf);
184		CFRelease(item_cf);
185		item_cf = NULL;
186	}
187	*dst = rv;
188	return 1;
189err:
190	Py_XDECREF(item_py);
191	if (rv) CFRelease(rv);
192	if (item_cf) CFRelease(item_cf);
193	return 0;		
194}
195
196int
197PyCF_Python2CF_mapping(PyObject *src, CFDictionaryRef *dst) {
198	CFMutableDictionaryRef rv = NULL;
199	PyObject *aslist = NULL;
200	CFTypeRef key_cf = NULL, value_cf = NULL;
201	PyObject *item_py = NULL, *key_py = NULL, *value_py = NULL;
202	int size, i;
203	
204	if( !PyMapping_Check(src) ) {
205		PyErr_Format(PyExc_TypeError,
206			"Cannot convert %.500s objects to CFDictionary",
207			src->ob_type->tp_name);
208		return 0;
209	}
210	size = PyMapping_Size(src);
211	rv = CFDictionaryCreateMutable((CFAllocatorRef)NULL, size,
212					&kCFTypeDictionaryKeyCallBacks,
213	                                &kCFTypeDictionaryValueCallBacks);
214	if (rv == NULL) {
215		PyMac_Error(resNotFound); 
216		goto err;
217	}
218	if ( (aslist = PyMapping_Items(src)) == NULL ) goto err;
219
220	for( i=0; i<size; i++) {
221		item_py = PySequence_GetItem(aslist, i);
222		if (item_py == NULL) goto err;
223		if (!PyArg_ParseTuple(item_py, "OO", &key_py, &value_py)) goto err;
224		if ( !PyCF_Python2CF(key_py, &key_cf) ) goto err;
225		if ( !PyCF_Python2CF(value_py, &value_cf) ) goto err;
226		CFDictionaryAddValue(rv, key_cf, value_cf);
227		CFRelease(key_cf);
228		key_cf = NULL;
229		CFRelease(value_cf);
230		value_cf = NULL;
231	}
232	*dst = rv;
233	return 1;
234err:
235	Py_XDECREF(item_py);
236	Py_XDECREF(aslist);
237	if (rv) CFRelease(rv);
238	if (key_cf) CFRelease(key_cf);
239	if (value_cf) CFRelease(value_cf);
240	return 0;		
241}
242
243int
244PyCF_Python2CF_simple(PyObject *src, CFTypeRef *dst) {
245	
246#if 0
247	if (PyObject_HasAttrString(src, "CFType")) {
248		*dst = PyObject_CallMethod(src, "CFType", "");
249		return (*dst != NULL);
250	}
251#endif
252	if (PyString_Check(src) || PyUnicode_Check(src)) 
253		return PyCF_Python2CF_string(src, (CFStringRef *)dst);
254	if (PyBool_Check(src)) {
255		if (src == Py_True)
256			*dst = kCFBooleanTrue;
257		else
258			*dst = kCFBooleanFalse;
259		return 1;
260	}
261	if (PyInt_Check(src)) {
262		long v = PyInt_AsLong(src);
263		*dst = CFNumberCreate(NULL, kCFNumberLongType, &v);
264		return 1;
265	}
266	if (PyFloat_Check(src)) {
267		double d = PyFloat_AsDouble(src);
268		*dst = CFNumberCreate(NULL, kCFNumberDoubleType, &d);
269		return 1;
270	}
271			
272	PyErr_Format(PyExc_TypeError,
273		  "Cannot convert %.500s objects to CFType",
274				     src->ob_type->tp_name);
275	return 0;
276}
277
278int
279PyCF_Python2CF_string(PyObject *src, CFStringRef *dst) {
280	char *chars;
281	CFIndex size;
282	UniChar *unichars;
283	
284	if (PyString_Check(src)) {
285		if (!PyArg_Parse(src, "es", "ascii", &chars))
286			return 0; /* This error is more descriptive than the general one below */
287		*dst = CFStringCreateWithCString((CFAllocatorRef)NULL, chars, kCFStringEncodingASCII);
288		PyMem_Free(chars);
289		return 1;
290	}
291	if (PyUnicode_Check(src)) {
292		/* We use the CF types here, if Python was configured differently that will give an error */
293		size = PyUnicode_GetSize(src);
294		if ((unichars = PyUnicode_AsUnicode(src)) == NULL ) goto err;
295		*dst = CFStringCreateWithCharacters((CFAllocatorRef)NULL, unichars, size);
296		return 1;
297	}
298err:
299	PyErr_Format(PyExc_TypeError,
300		  "Cannot convert %.500s objects to CFString",
301				     src->ob_type->tp_name);
302	return 0;
303}