symbian-qemu-0.9.1-12/python-2.6.1/Mac/Modules/cf/pycfbridge.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 
       
    16 PyObject *
       
    17 PyCF_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 
       
    32 PyObject *
       
    33 PyCF_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;
       
    51 err:
       
    52 	Py_XDECREF(item_py);
       
    53 	Py_DECREF(rv);
       
    54 	return NULL;
       
    55 }
       
    56 
       
    57 PyObject *
       
    58 PyCF_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;
       
    90 err:
       
    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 
       
    99 PyObject *
       
   100 PyCF_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? */
       
   126 PyObject *
       
   127 PyCF_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 
       
   146 int
       
   147 PyCF_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 
       
   158 int
       
   159 PyCF_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;
       
   189 err:
       
   190 	Py_XDECREF(item_py);
       
   191 	if (rv) CFRelease(rv);
       
   192 	if (item_cf) CFRelease(item_cf);
       
   193 	return 0;		
       
   194 }
       
   195 
       
   196 int
       
   197 PyCF_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;
       
   234 err:
       
   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 
       
   243 int
       
   244 PyCF_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 
       
   278 int
       
   279 PyCF_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 	}
       
   298 err:
       
   299 	PyErr_Format(PyExc_TypeError,
       
   300 		  "Cannot convert %.500s objects to CFString",
       
   301 				     src->ob_type->tp_name);
       
   302 	return 0;
       
   303 }