blob: 76c5ad4c4d08fd8f538a5a0782bc6b8832be1d9c [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
29 typeid = CFGetTypeID(src);
30 if (typeid == CFArrayGetTypeID())
31 return PyCF_CF2Python_sequence((CFArrayRef)src);
32 if (typeid == CFDictionaryGetTypeID())
33 return PyCF_CF2Python_mapping((CFDictionaryRef)src);
34 return PyCF_CF2Python_simple(src);
35}
36
37PyObject *
38PyCF_CF2Python_sequence(CFArrayRef src) {
39 PyErr_SetString(PyExc_SystemError, "Not yet implemented");
40 return NULL;
41}
42
43PyObject *
44PyCF_CF2Python_mapping(CFTypeRef src) {
45 PyErr_SetString(PyExc_SystemError, "Not yet implemented");
46 return NULL;
47}
48
49PyObject *
50PyCF_CF2Python_simple(CFTypeRef src) {
51 CFTypeID typeid;
52
53 typeid = CFGetTypeID(src);
54 if (typeid == CFStringGetTypeID())
55 return PyCF_CF2Python_string((CFStringRef)src);
56 PyMac_Error(resNotFound);
57 return NULL;
58}
59
60/* Unsure - Return unicode or 8 bit strings? */
61PyObject *
62PyCF_CF2Python_string(CFStringRef src) {
63 int size = CFStringGetLength(src)+1;
64 Py_UNICODE *data = malloc(size*sizeof(Py_UNICODE));
65 CFRange range;
66 PyObject *rv;
67
68 range.location = 0;
69 range.length = size;
70 if( data == NULL ) return PyErr_NoMemory();
71 CFStringGetCharacters(src, range, data);
72 rv = (PyObject *)PyUnicode_FromUnicode(data, size);
73 free(data);
74 return rv;
75}
76
77/* ---------------------------------------- */
78/* Python objects to CoreFoundation objects */
79/* ---------------------------------------- */
80
81int
82PyCF_Python2CF(PyObject *src, CFTypeRef *dst) {
83
84 if (PySequence_Check(src))
85 return PyCF_Python2CF_sequence(src, (CFArrayRef *)dst);
86 if (PyMapping_Check(src))
87 return PyCF_Python2CF_mapping(src, (CFDictionaryRef *)dst);
88 return PyCF_Python2CF_simple(src, dst);
89}
90
91int
92PyCF_Python2CF_sequence(PyObject *src, CFArrayRef *dst) {
93 CFArrayRef rv = NULL;
94 CFTypeRef item_cf = NULL;
95 PyObject *item_py = NULL;
96 int size, i;
97
98 size = PySequence_Size(src);
99 rv = CFArrayCreateMutable((CFAllocatorRef)NULL, size, &kCFTypeArrayCallBacks);
100 if (rv == NULL) {
101 PyMac_Error(resNotFound);
102 goto err;
103 }
104
105 for( i=0; i<size; i++) {
106 item_py = PySequence_GetItem(src, i);
107 if (item_py == NULL) goto err;
108 if ( !PyCF_Python2CF(item_py, &item_cf)) goto err;
109 Py_DECREF(item_py);
110 CFArraySetValueAtIndex(rv, i, item_cf);
111 CFRelease(item_cf);
112 item_cf = NULL;
113 }
114 *dst = rv;
115 return 1;
116err:
117 Py_XDECREF(item_py);
118 if (rv) CFRelease(rv);
119 if (item_cf) CFRelease(item_cf);
120 return 0;
121}
122
123int
124PyCF_Python2CF_mapping(PyObject *src, CFDictionaryRef *dst) {
125 CFDictionaryRef rv = NULL;
126 PyObject *aslist = NULL;
127 CFTypeRef key_cf = NULL, value_cf = NULL;
128 PyObject *item_py = NULL, *key_py = NULL, *value_py = NULL;
129 int size, i;
130
131 size = PyMapping_Size(src);
132 rv = CFDictionaryCreateMutable((CFAllocatorRef)NULL, size,
133 &kCFTypeDictionaryKeyCallBacks,
134 &kCFTypeDictionaryValueCallBacks);
135 if (rv == NULL) {
136 PyMac_Error(resNotFound);
137 goto err;
138 }
139 if ( (aslist = PyMapping_Items(src)) == NULL ) goto err;
140
141 for( i=0; i<size; i++) {
142 item_py = PySequence_GetItem(aslist, i);
143 if (item_py == NULL) goto err;
144 if (!PyArg_ParseTuple(item_py, "OO", key_py, value_py)) goto err;
145 if ( !PyCF_Python2CF(key_py, &key_cf) ) goto err;
146 Py_DECREF(key_py);
147 if ( !PyCF_Python2CF(value_cf, &key_cf) ) goto err;
148 Py_DECREF(value_py);
149 CFDictionaryAddValue(rv, key_cf, value_cf);
150 CFRelease(key_cf);
151 key_cf = NULL;
152 CFRelease(value_cf);
153 value_cf = NULL;
154 }
155 *dst = rv;
156 return 1;
157err:
158 Py_XDECREF(item_py);
159 Py_XDECREF(key_py);
160 Py_XDECREF(value_py);
161 Py_XDECREF(aslist);
162 if (rv) CFRelease(rv);
163 if (key_cf) CFRelease(key_cf);
164 if (value_cf) CFRelease(value_cf);
165 return 0;
166}
167
168int
169PyCF_Python2CF_simple(PyObject *src, CFTypeRef *dst) {
170
171 if (PyObject_HasAttrString(src, "CFType")) {
172 *dst = PyObject_CallMethod(src, "CFType", "");
173 return (*dst != NULL);
174 }
175 if (PyString_Check(src) || PyUnicode_Check(src))
176 return PyCF_Python2CF_string(src, (CFStringRef *)dst);
177 PyErr_Format(PyExc_TypeError,
178 "Cannot convert %.500s objects to CF",
179 src->ob_type->tp_name);
180 return 0;
181}
182
183int
184PyCF_Python2CF_string(PyObject *src, CFStringRef *dst) {
185 char *chars;
186 CFIndex size;
187 UniChar *unichars;
188
189 if (PyString_Check(src)) {
190 if ((chars = PyString_AsString(src)) == NULL ) goto err;
191 *dst = CFStringCreateWithCString((CFAllocatorRef)NULL, chars, 0);
192 return 1;
193 }
194 if (PyUnicode_Check(src)) {
195 /* We use the CF types here, if Python was configured differently that will give an error */
196 size = PyUnicode_GetSize(src);
197 if ((unichars = PyUnicode_AsUnicode(src)) == NULL ) goto err;
198 *dst = CFStringCreateWithCharacters((CFAllocatorRef)NULL, unichars, size);
199 return 1;
200 }
201err:
202 PyErr_Format(PyExc_TypeError,
203 "Cannot convert %.500s objects to CF",
204 src->ob_type->tp_name);
205 return 0;
206}