2 ** Convert objects from Python to CoreFoundation and vice-versa.
5 #ifdef WITHOUT_FRAMEWORKS
10 #include <CFDictionary.h>
14 #include <CoreServices/CoreServices.h>
19 #include "pycfbridge.h"
22 /* ---------------------------------------- */
23 /* CoreFoundation objects to Python objects */
24 /* ---------------------------------------- */
27 PyCF_CF2Python(CFTypeRef src
) {
34 typeid = CFGetTypeID(src
);
35 if (typeid == CFArrayGetTypeID())
36 return PyCF_CF2Python_sequence((CFArrayRef
)src
);
37 if (typeid == CFDictionaryGetTypeID())
38 return PyCF_CF2Python_mapping((CFDictionaryRef
)src
);
39 return PyCF_CF2Python_simple(src
);
43 PyCF_CF2Python_sequence(CFArrayRef src
) {
44 int size
= CFArrayGetCount(src
);
47 PyObject
*item_py
= NULL
;
50 if ( (rv
=PyList_New(size
)) == NULL
)
52 for(i
=0; i
<size
; i
++) {
53 item_cf
= CFArrayGetValueAtIndex(src
, i
);
54 if (item_cf
== NULL
) goto err
;
55 item_py
= PyCF_CF2Python(item_cf
);
56 if (item_py
== NULL
) goto err
;
57 if (PyList_SetItem(rv
, i
, item_py
) < 0) goto err
;
68 PyCF_CF2Python_mapping(CFTypeRef src
) {
69 int size
= CFDictionaryGetCount(src
);
71 CFTypeRef
*allkeys
= NULL
, *allvalues
= NULL
;
72 CFTypeRef key_cf
, value_cf
;
73 PyObject
*key_py
= NULL
, *value_py
= NULL
;
76 allkeys
= malloc(size
*sizeof(CFTypeRef
*));
77 if (allkeys
== NULL
) {
81 allvalues
= malloc(size
*sizeof(CFTypeRef
*));
82 if (allvalues
== NULL
) {
86 if ( (rv
=PyDict_New()) == NULL
) goto err
;
87 CFDictionaryGetKeysAndValues(src
, allkeys
, allvalues
);
88 for(i
=0; i
<size
; i
++) {
90 value_cf
= allvalues
[i
];
91 key_py
= PyCF_CF2Python(key_cf
);
92 if (key_py
== NULL
) goto err
;
93 value_py
= PyCF_CF2Python(value_cf
);
94 if (value_py
== NULL
) goto err
;
95 if (PyDict_SetItem(rv
, key_py
, value_py
) < 0) goto err
;
102 Py_XDECREF(value_py
);
110 PyCF_CF2Python_simple(CFTypeRef src
) {
113 typeid = CFGetTypeID(src
);
114 if (typeid == CFStringGetTypeID())
115 return PyCF_CF2Python_string((CFStringRef
)src
);
116 if (typeid == CFBooleanGetTypeID())
117 return PyBool_FromLong((long)CFBooleanGetValue(src
));
118 if (typeid == CFNumberGetTypeID()) {
119 if (CFNumberIsFloatType(src
)) {
121 CFNumberGetValue(src
, kCFNumberDoubleType
, &d
);
122 return PyFloat_FromDouble(d
);
125 if (!CFNumberGetValue(src
, kCFNumberLongType
, &l
))
126 /* XXXX Out of range! */;
127 return PyInt_FromLong(l
);
130 /* XXXX Should return as CFTypeRef, really... */
131 PyMac_Error(resNotFound
);
135 /* Unsure - Return unicode or 8 bit strings? */
137 PyCF_CF2Python_string(CFStringRef src
) {
138 int size
= CFStringGetLength(src
)+1;
139 Py_UNICODE
*data
= malloc(size
*sizeof(Py_UNICODE
));
145 if( data
== NULL
) return PyErr_NoMemory();
146 CFStringGetCharacters(src
, range
, data
);
147 rv
= (PyObject
*)PyUnicode_FromUnicode(data
, size
-1);
152 /* ---------------------------------------- */
153 /* Python objects to CoreFoundation objects */
154 /* ---------------------------------------- */
157 PyCF_Python2CF(PyObject
*src
, CFTypeRef
*dst
) {
159 if (PyString_Check(src
) || PyUnicode_Check(src
))
160 return PyCF_Python2CF_simple(src
, dst
);
161 if (PySequence_Check(src
))
162 return PyCF_Python2CF_sequence(src
, (CFArrayRef
*)dst
);
163 if (PyMapping_Check(src
))
164 return PyCF_Python2CF_mapping(src
, (CFDictionaryRef
*)dst
);
165 return PyCF_Python2CF_simple(src
, dst
);
169 PyCF_Python2CF_sequence(PyObject
*src
, CFArrayRef
*dst
) {
170 CFMutableArrayRef rv
= NULL
;
171 CFTypeRef item_cf
= NULL
;
172 PyObject
*item_py
= NULL
;
175 if( !PySequence_Check(src
) ) {
176 PyErr_Format(PyExc_TypeError
,
177 "Cannot convert %.500s objects to CFArray",
178 src
->ob_type
->tp_name
);
181 size
= PySequence_Size(src
);
182 rv
= CFArrayCreateMutable((CFAllocatorRef
)NULL
, size
, &kCFTypeArrayCallBacks
);
184 PyMac_Error(resNotFound
);
188 for( i
=0; i
<size
; i
++) {
189 item_py
= PySequence_GetItem(src
, i
);
190 if (item_py
== NULL
) goto err
;
191 if ( !PyCF_Python2CF(item_py
, &item_cf
)) goto err
;
193 CFArraySetValueAtIndex(rv
, i
, item_cf
);
201 if (rv
) CFRelease(rv
);
202 if (item_cf
) CFRelease(item_cf
);
207 PyCF_Python2CF_mapping(PyObject
*src
, CFDictionaryRef
*dst
) {
208 CFMutableDictionaryRef rv
= NULL
;
209 PyObject
*aslist
= NULL
;
210 CFTypeRef key_cf
= NULL
, value_cf
= NULL
;
211 PyObject
*item_py
= NULL
, *key_py
= NULL
, *value_py
= NULL
;
214 if( !PyMapping_Check(src
) ) {
215 PyErr_Format(PyExc_TypeError
,
216 "Cannot convert %.500s objects to CFDictionary",
217 src
->ob_type
->tp_name
);
220 size
= PyMapping_Size(src
);
221 rv
= CFDictionaryCreateMutable((CFAllocatorRef
)NULL
, size
,
222 &kCFTypeDictionaryKeyCallBacks
,
223 &kCFTypeDictionaryValueCallBacks
);
225 PyMac_Error(resNotFound
);
228 if ( (aslist
= PyMapping_Items(src
)) == NULL
) goto err
;
230 for( i
=0; i
<size
; i
++) {
231 item_py
= PySequence_GetItem(aslist
, i
);
232 if (item_py
== NULL
) goto err
;
233 if (!PyArg_ParseTuple(item_py
, "OO", &key_py
, &value_py
)) goto err
;
234 if ( !PyCF_Python2CF(key_py
, &key_cf
) ) goto err
;
235 if ( !PyCF_Python2CF(value_py
, &value_cf
) ) goto err
;
236 CFDictionaryAddValue(rv
, key_cf
, value_cf
);
247 if (rv
) CFRelease(rv
);
248 if (key_cf
) CFRelease(key_cf
);
249 if (value_cf
) CFRelease(value_cf
);
254 PyCF_Python2CF_simple(PyObject
*src
, CFTypeRef
*dst
) {
257 if (PyObject_HasAttrString(src
, "CFType")) {
258 *dst
= PyObject_CallMethod(src
, "CFType", "");
259 return (*dst
!= NULL
);
262 if (PyString_Check(src
) || PyUnicode_Check(src
))
263 return PyCF_Python2CF_string(src
, (CFStringRef
*)dst
);
264 if (PyBool_Check(src
)) {
266 *dst
= kCFBooleanTrue
;
268 *dst
= kCFBooleanFalse
;
271 if (PyInt_Check(src
)) {
272 long v
= PyInt_AsLong(src
);
273 *dst
= CFNumberCreate(NULL
, kCFNumberLongType
, &v
);
276 if (PyFloat_Check(src
)) {
277 double d
= PyFloat_AsDouble(src
);
278 *dst
= CFNumberCreate(NULL
, kCFNumberDoubleType
, &d
);
282 PyErr_Format(PyExc_TypeError
,
283 "Cannot convert %.500s objects to CFType",
284 src
->ob_type
->tp_name
);
289 PyCF_Python2CF_string(PyObject
*src
, CFStringRef
*dst
) {
294 if (PyString_Check(src
)) {
295 if ((chars
= PyString_AsString(src
)) == NULL
) goto err
;
296 *dst
= CFStringCreateWithCString((CFAllocatorRef
)NULL
, chars
, 0);
299 if (PyUnicode_Check(src
)) {
300 /* We use the CF types here, if Python was configured differently that will give an error */
301 size
= PyUnicode_GetSize(src
);
302 if ((unichars
= PyUnicode_AsUnicode(src
)) == NULL
) goto err
;
303 *dst
= CFStringCreateWithCharacters((CFAllocatorRef
)NULL
, unichars
, size
);
307 PyErr_Format(PyExc_TypeError
,
308 "Cannot convert %.500s objects to CFString",
309 src
->ob_type
->tp_name
);