ยปCore Development>Code coverage>Mac/Modules/cf/pycfbridge.c

Python code coverage for Mac/Modules/cf/pycfbridge.c

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