blob: a44c4041204d288290e6fa156eaa220accdd74cf [file] [log] [blame]
Jack Jansenefaffae2002-05-05 21:48:12 +00001/*
2** Convert objects from Python to CoreFoundation and vice-versa.
3*/
4
5#ifdef WITHOUT_FRAMEWORKS
6#include <CFBase.h>
7#include <CFArray.h>
8#include <CFData.h>
9#include <CFDictionary.h>
10#include <CFString.h>
11#include <CFURL.h>
12#else
13#include <CoreServices/CoreServices.h>
14#endif
15
16#include "Python.h"
17#include "macglue.h"
18#include "pycfbridge.h"
19
20
21/* ---------------------------------------- */
22/* CoreFoundation objects to Python objects */
23/* ---------------------------------------- */
24
25PyObject *
26PyCF_CF2Python(CFTypeRef src) {
27 CFTypeID typeid;
28
Jack Jansen5ad6f7a2002-05-07 23:00:03 +000029 if( src == NULL ) {
30 Py_INCREF(Py_None);
31 return Py_None;
32 }
Jack Jansenefaffae2002-05-05 21:48:12 +000033 typeid = CFGetTypeID(src);
34 if (typeid == CFArrayGetTypeID())
35 return PyCF_CF2Python_sequence((CFArrayRef)src);
36 if (typeid == CFDictionaryGetTypeID())
37 return PyCF_CF2Python_mapping((CFDictionaryRef)src);
38 return PyCF_CF2Python_simple(src);
39}
40
41PyObject *
42PyCF_CF2Python_sequence(CFArrayRef src) {
Jack Jansen5ad6f7a2002-05-07 23:00:03 +000043 int size = CFArrayGetCount(src);
44 PyObject *rv;
45 CFTypeRef item_cf;
46 PyObject *item_py = NULL;
47 int i;
48
49 if ( (rv=PyList_New(size)) == NULL )
50 return NULL;
51 for(i=0; i<size; i++) {
52 item_cf = CFArrayGetValueAtIndex(src, i);
53 if (item_cf == NULL ) goto err;
54 item_py = PyCF_CF2Python(item_cf);
55 if (item_py == NULL ) goto err;
Jack Jansen1df628d2002-05-08 15:29:33 +000056 if (PyList_SetItem(rv, i, item_py) < 0) goto err;
Jack Jansen5ad6f7a2002-05-07 23:00:03 +000057 item_py = NULL;
58 }
59 return rv;
60err:
61 Py_XDECREF(item_py);
62 Py_DECREF(rv);
Jack Jansenefaffae2002-05-05 21:48:12 +000063 return NULL;
64}
65
66PyObject *
67PyCF_CF2Python_mapping(CFTypeRef src) {
Jack Jansen5ad6f7a2002-05-07 23:00:03 +000068 int size = CFDictionaryGetCount(src);
69 PyObject *rv;
70 CFTypeRef *allkeys, *allvalues;
71 CFTypeRef key_cf, value_cf;
72 PyObject *key_py = NULL, *value_py = NULL;
73 int i;
74
75 allkeys = malloc(size*sizeof(CFTypeRef *));
76 if (allkeys == NULL) return PyErr_NoMemory();
77 allvalues = malloc(size*sizeof(CFTypeRef *));
78 if (allvalues == NULL) return PyErr_NoMemory();
79 if ( (rv=PyDict_New()) == NULL )
80 return NULL;
81 CFDictionaryGetKeysAndValues(src, allkeys, allvalues);
82 for(i=0; i<size; i++) {
83 key_cf = allkeys[i];
84 value_cf = allvalues[i];
85 key_py = PyCF_CF2Python(key_cf);
86 if (key_py == NULL ) goto err;
87 value_py = PyCF_CF2Python(value_py);
88 if (value_py == NULL ) goto err;
Jack Jansen1df628d2002-05-08 15:29:33 +000089 if (PyDict_SetItem(rv, key_py, value_py) < 0) goto err;
Jack Jansen5ad6f7a2002-05-07 23:00:03 +000090 key_py = NULL;
91 value_py = NULL;
92 }
93 return rv;
94err:
95 Py_XDECREF(key_py);
96 Py_XDECREF(value_py);
97 Py_DECREF(rv);
98 free(allkeys);
99 free(allvalues);
Jack Jansenefaffae2002-05-05 21:48:12 +0000100 return NULL;
101}
102
103PyObject *
104PyCF_CF2Python_simple(CFTypeRef src) {
105 CFTypeID typeid;
106
107 typeid = CFGetTypeID(src);
108 if (typeid == CFStringGetTypeID())
109 return PyCF_CF2Python_string((CFStringRef)src);
110 PyMac_Error(resNotFound);
111 return NULL;
112}
113
114/* Unsure - Return unicode or 8 bit strings? */
115PyObject *
116PyCF_CF2Python_string(CFStringRef src) {
117 int size = CFStringGetLength(src)+1;
118 Py_UNICODE *data = malloc(size*sizeof(Py_UNICODE));
119 CFRange range;
120 PyObject *rv;
121
122 range.location = 0;
123 range.length = size;
124 if( data == NULL ) return PyErr_NoMemory();
125 CFStringGetCharacters(src, range, data);
126 rv = (PyObject *)PyUnicode_FromUnicode(data, size);
127 free(data);
128 return rv;
129}
130
131/* ---------------------------------------- */
132/* Python objects to CoreFoundation objects */
133/* ---------------------------------------- */
134
135int
136PyCF_Python2CF(PyObject *src, CFTypeRef *dst) {
137
Jack Jansen1df628d2002-05-08 15:29:33 +0000138 if (PyString_Check(src) || PyUnicode_Check(src))
139 return PyCF_Python2CF_simple(src, dst);
Jack Jansenefaffae2002-05-05 21:48:12 +0000140 if (PySequence_Check(src))
141 return PyCF_Python2CF_sequence(src, (CFArrayRef *)dst);
142 if (PyMapping_Check(src))
143 return PyCF_Python2CF_mapping(src, (CFDictionaryRef *)dst);
144 return PyCF_Python2CF_simple(src, dst);
145}
146
147int
148PyCF_Python2CF_sequence(PyObject *src, CFArrayRef *dst) {
Jack Jansen5ad6f7a2002-05-07 23:00:03 +0000149 CFMutableArrayRef rv = NULL;
Jack Jansenefaffae2002-05-05 21:48:12 +0000150 CFTypeRef item_cf = NULL;
151 PyObject *item_py = NULL;
152 int size, i;
153
154 size = PySequence_Size(src);
155 rv = CFArrayCreateMutable((CFAllocatorRef)NULL, size, &kCFTypeArrayCallBacks);
156 if (rv == NULL) {
157 PyMac_Error(resNotFound);
158 goto err;
159 }
160
161 for( i=0; i<size; i++) {
162 item_py = PySequence_GetItem(src, i);
163 if (item_py == NULL) goto err;
164 if ( !PyCF_Python2CF(item_py, &item_cf)) goto err;
165 Py_DECREF(item_py);
166 CFArraySetValueAtIndex(rv, i, item_cf);
167 CFRelease(item_cf);
168 item_cf = NULL;
169 }
170 *dst = rv;
171 return 1;
172err:
173 Py_XDECREF(item_py);
174 if (rv) CFRelease(rv);
175 if (item_cf) CFRelease(item_cf);
176 return 0;
177}
178
179int
180PyCF_Python2CF_mapping(PyObject *src, CFDictionaryRef *dst) {
Jack Jansen5ad6f7a2002-05-07 23:00:03 +0000181 CFMutableDictionaryRef rv = NULL;
Jack Jansenefaffae2002-05-05 21:48:12 +0000182 PyObject *aslist = NULL;
183 CFTypeRef key_cf = NULL, value_cf = NULL;
184 PyObject *item_py = NULL, *key_py = NULL, *value_py = NULL;
185 int size, i;
186
187 size = PyMapping_Size(src);
188 rv = CFDictionaryCreateMutable((CFAllocatorRef)NULL, size,
Jack Jansen5ad6f7a2002-05-07 23:00:03 +0000189 &kCFTypeDictionaryKeyCallBacks,
Jack Jansenefaffae2002-05-05 21:48:12 +0000190 &kCFTypeDictionaryValueCallBacks);
191 if (rv == NULL) {
192 PyMac_Error(resNotFound);
193 goto err;
194 }
195 if ( (aslist = PyMapping_Items(src)) == NULL ) goto err;
196
197 for( i=0; i<size; i++) {
198 item_py = PySequence_GetItem(aslist, i);
199 if (item_py == NULL) goto err;
200 if (!PyArg_ParseTuple(item_py, "OO", key_py, value_py)) goto err;
201 if ( !PyCF_Python2CF(key_py, &key_cf) ) goto err;
202 Py_DECREF(key_py);
Jack Jansen5ad6f7a2002-05-07 23:00:03 +0000203 if ( !PyCF_Python2CF(value_py, &value_cf) ) goto err;
Jack Jansenefaffae2002-05-05 21:48:12 +0000204 Py_DECREF(value_py);
205 CFDictionaryAddValue(rv, key_cf, value_cf);
206 CFRelease(key_cf);
207 key_cf = NULL;
208 CFRelease(value_cf);
209 value_cf = NULL;
210 }
211 *dst = rv;
212 return 1;
213err:
214 Py_XDECREF(item_py);
215 Py_XDECREF(key_py);
216 Py_XDECREF(value_py);
217 Py_XDECREF(aslist);
218 if (rv) CFRelease(rv);
219 if (key_cf) CFRelease(key_cf);
220 if (value_cf) CFRelease(value_cf);
221 return 0;
222}
223
224int
225PyCF_Python2CF_simple(PyObject *src, CFTypeRef *dst) {
226
227 if (PyObject_HasAttrString(src, "CFType")) {
228 *dst = PyObject_CallMethod(src, "CFType", "");
229 return (*dst != NULL);
230 }
231 if (PyString_Check(src) || PyUnicode_Check(src))
232 return PyCF_Python2CF_string(src, (CFStringRef *)dst);
233 PyErr_Format(PyExc_TypeError,
234 "Cannot convert %.500s objects to CF",
235 src->ob_type->tp_name);
236 return 0;
237}
238
239int
240PyCF_Python2CF_string(PyObject *src, CFStringRef *dst) {
241 char *chars;
242 CFIndex size;
243 UniChar *unichars;
244
245 if (PyString_Check(src)) {
246 if ((chars = PyString_AsString(src)) == NULL ) goto err;
247 *dst = CFStringCreateWithCString((CFAllocatorRef)NULL, chars, 0);
248 return 1;
249 }
250 if (PyUnicode_Check(src)) {
251 /* We use the CF types here, if Python was configured differently that will give an error */
252 size = PyUnicode_GetSize(src);
253 if ((unichars = PyUnicode_AsUnicode(src)) == NULL ) goto err;
254 *dst = CFStringCreateWithCharacters((CFAllocatorRef)NULL, unichars, size);
255 return 1;
256 }
257err:
258 PyErr_Format(PyExc_TypeError,
259 "Cannot convert %.500s objects to CF",
260 src->ob_type->tp_name);
261 return 0;
262}