1/*
2 * Some utility functions...
3 *
4 * TODO: Documentation
5 */
6
7#include "pyobjc.h"
8
9#import <Foundation/Foundation.h>
10
11PyObject* PyObjCExc_Error;
12PyObject* PyObjCExc_NoSuchClassError;
13PyObject* PyObjCExc_InternalError;
14PyObject* PyObjCExc_UnInitDeallocWarning;
15PyObject* PyObjCExc_ObjCRevivalWarning;
16PyObject* PyObjCExc_LockError;
17PyObject* PyObjCExc_BadPrototypeError;
18PyObject* PyObjCExc_UnknownPointerError;
19
20
21
22int
23PyObjCUtil_Init(PyObject* module)
24{
25#define NEW_EXC(identifier, name, base_class) \
26	identifier = PyErr_NewException("objc."name, base_class, NULL); \
27	if (identifier == NULL) return -1; \
28	Py_INCREF(identifier); \
29	if (PyModule_AddObject(module, name, identifier) < 0) return -1;
30
31	NEW_EXC(PyObjCExc_Error, "error", NULL);
32	NEW_EXC(PyObjCExc_NoSuchClassError, "nosuchclass_error", PyObjCExc_Error);
33	NEW_EXC(PyObjCExc_InternalError, "internal_error", PyObjCExc_Error);
34	NEW_EXC(PyObjCExc_UnInitDeallocWarning, "UninitializedDeallocWarning", PyExc_Warning);
35	NEW_EXC(PyObjCExc_ObjCRevivalWarning, "RevivedObjectiveCObjectWarning", PyExc_Warning);
36	NEW_EXC(PyObjCExc_LockError, "LockError", PyObjCExc_Error);
37	NEW_EXC(PyObjCExc_BadPrototypeError, "BadPrototypeError", PyObjCExc_Error);
38	NEW_EXC(PyObjCExc_UnknownPointerError, "UnknownPointerError", PyObjCExc_Error);
39
40	return 0;
41}
42
43static PyObject*
44ObjCErr_PyExcForName(const char* value)
45{
46	/* XXX: This table should be changeable from python */
47	if (strcmp(value, "NSRangeException") == 0) {
48		return PyExc_IndexError;
49	}  else if (strcmp(value, "NSInvalidArgumentException") == 0) {
50		return PyExc_ValueError;
51	}  else if (strcmp(value, "NSMallocException") == 0) {
52		return PyExc_MemoryError;
53	}  else if (strcmp(value, "NSUnknownKeyException") == 0) {
54		return PyExc_KeyError;
55	}
56
57	return PyObjCExc_Error;
58}
59
60
61void
62PyObjCErr_FromObjC(NSException* localException)
63{
64	NSDictionary* userInfo;
65	PyObject*     dict;
66	PyObject*     exception;
67	PyObject*     v;
68	PyObject*	  buf;
69	PyObject*     exc_type;
70	PyObject*     exc_value;
71	PyObject*     exc_traceback;
72	PyObject*     c_localException_name;
73	PyObject*     c_localException_reason;
74	NSObject* t;
75
76	PyGILState_STATE state;
77
78	state = PyGILState_Ensure();
79
80	if (![localException isKindOfClass:[NSException class]]) {
81		/* We caught some random objects as the exception, so the minimal possible
82		 */
83		PyErr_SetString(PyObjCExc_Error, "non-NSException object caught");
84
85		PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
86		if (!exc_value || !PyObject_IsInstance(exc_value, exc_type)) {
87			PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback);
88		}
89
90		PyObject* exc = PyObjC_IdToPython(localException);
91		if (exc == NULL) {
92			PyErr_Clear();
93		} else {
94			PyObject_SetAttrString(exc_value, "_pyobjc_exc_", exc);
95		}
96		Py_CLEAR(exc);
97		PyErr_Restore(exc_type, exc_value, exc_traceback);
98		PyGILState_Release(state);
99		return;
100	}
101
102	exception = ObjCErr_PyExcForName([[localException name] UTF8String]);
103
104	userInfo = [localException userInfo];
105	if (userInfo) {
106		id val;
107
108		val = [userInfo objectForKey:@"__pyobjc_exc_type__"];
109		if (val) {
110			exc_type = [val pyObject];
111			exc_value = [[userInfo objectForKey:@"__pyobjc_exc_value__"]  pyObject];
112			exc_traceback = [[userInfo objectForKey:@"__pyobjc_exc_traceback__"]  pyObject];
113
114			/* -pyObject returns a borrowed reference and
115			 * PyErr_Restore steals one from us.
116			 */
117			Py_INCREF(exc_type);
118			Py_XINCREF(exc_value);
119			Py_XINCREF(exc_traceback);
120
121			PyErr_Restore(exc_type, exc_value, exc_traceback);
122			PyGILState_Release(state);
123			return;
124		}
125	}
126
127	t = [localException name];
128	c_localException_name = pythonify_c_value(@encode(NSObject*), &t);
129	if (c_localException_name == NULL) {
130		return;
131	}
132
133	t = [localException reason];
134	c_localException_reason = pythonify_c_value(@encode(NSObject*), &t);
135	if (c_localException_reason == NULL) {
136		Py_DECREF(c_localException_name);
137		return;
138	}
139
140	dict = PyDict_New();
141	if (dict == NULL) {
142		Py_DECREF(c_localException_name);
143		Py_DECREF(c_localException_reason);
144		return;
145	}
146	PyDict_SetItemString(dict, "name", c_localException_name);
147	Py_DECREF(c_localException_name);
148
149	PyDict_SetItemString(dict, "reason",  c_localException_reason);
150	Py_DECREF(c_localException_reason);
151	if (userInfo) {
152		v = PyObjCObject_New(userInfo, PyObjCObject_kDEFAULT, YES);
153		if (v != NULL) {
154			PyDict_SetItemString(dict, "userInfo", v);
155			Py_DECREF(v);
156		} else {
157			PyErr_Clear();
158		}
159	} else {
160		PyDict_SetItemString(dict, "userInfo", Py_None);
161	}
162
163	if ([[localException reason] UTF8String]) {
164		 buf = PyText_FromFormat("%s - %s",
165		       [[localException name] UTF8String],
166		       [[localException reason] UTF8String]);
167	} else {
168		 buf = PyText_FromFormat("%s",
169		       [[localException name] UTF8String]);
170	}
171	PyErr_SetObject(exception, buf);
172	PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
173	if (!exc_value || !PyObject_IsInstance(exc_value, exc_type)) {
174		PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback);
175	}
176
177	PyObject_SetAttrString(exc_value, "_pyobjc_info_", dict);
178	Py_DECREF(dict); dict = NULL;
179	PyObject_SetAttrString(exc_value, "name", c_localException_name);
180	PyErr_Restore(exc_type, exc_value, exc_traceback);
181	PyGILState_Release(state);
182}
183
184void
185PyObjCErr_ToObjC(void)
186{
187	PyObjCErr_ToObjCWithGILState(NULL);
188}
189
190
191NSException*
192PyObjCErr_AsExc(void)
193{
194	PyObject* exc_type;
195	PyObject* exc_value;
196	PyObject* exc_traceback;
197	PyObject* args;
198	PyObject* repr;
199	PyObject* typerepr;
200	NSException* val;
201	NSMutableDictionary* userInfo;
202
203	PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
204	if (exc_type == NULL) {
205		return nil;
206	}
207
208	PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback);
209
210	args = PyObject_GetAttrString(exc_value, "_pyobjc_exc_");
211	if (args == NULL) {
212		PyErr_Clear();
213	} else {
214		id result;
215
216		if (depythonify_c_value(@encode(id), args, &result) == -1) {
217			abort();
218		}
219		return result;
220	}
221
222	args = PyObject_GetAttrString(exc_value, "_pyobjc_info_");
223	if (args == NULL) {
224		PyErr_Clear();
225	} else {
226		/* This may be an exception that started out in
227		 * Objective-C code.
228		 */
229		PyObject* v;
230		NSString* reason = NULL;
231		NSString* name = NULL;
232
233		v = PyDict_GetItemString(args, "reason");
234		if (v) {
235			if (depythonify_c_value(@encode(NSObject*), v, &reason) < 0) {
236				PyErr_Clear();
237			}
238		}
239
240		v = PyDict_GetItemString(args, "name");
241		if (v) {
242			if (depythonify_c_value(@encode(NSObject*), v, &name) < 0) {
243				PyErr_Clear();
244			}
245		}
246
247		v = PyDict_GetItemString(args, "userInfo");
248		if (v && PyObjCObject_Check(v)) {
249			userInfo = PyObjCObject_GetObject(v);
250		} else {
251			userInfo = nil;
252			PyErr_Clear();
253		}
254
255		if (name && reason) {
256			val = [NSException exceptionWithName:name
257				     reason:reason
258				     userInfo:userInfo];
259			Py_DECREF(args);
260			Py_XDECREF(exc_type);
261			Py_XDECREF(exc_value);
262			Py_XDECREF(exc_traceback);
263
264			return val;
265		}
266	}
267
268	repr = PyObject_Str(exc_value);
269	typerepr = PyObject_Str(exc_type);
270	userInfo = [NSMutableDictionary dictionaryWithCapacity: 3];
271	[userInfo setObject:
272		[[[OC_PythonObject alloc] initWithPyObject:exc_type] autorelease]
273		forKey:@"__pyobjc_exc_type__"];
274	if (exc_value != NULL)
275		[userInfo setObject:
276			[[[OC_PythonObject alloc] initWithPyObject:exc_value] autorelease]
277			forKey:@"__pyobjc_exc_value__"];
278	if (exc_traceback != NULL)
279		[userInfo setObject:
280			[[[OC_PythonObject alloc] initWithPyObject:exc_traceback] autorelease]
281			forKey:@"__pyobjc_exc_traceback__"];
282
283	val = [NSException
284		exceptionWithName:@"OC_PythonException"
285			   reason:[NSString stringWithFormat:@"%@: %@", typerepr?PyObjC_PythonToId(typerepr):NULL, repr?PyObjC_PythonToId(repr):NULL]
286		userInfo:userInfo];
287
288	Py_XDECREF(typerepr);
289	Py_XDECREF(repr);
290
291	if (PyObjC_VerboseLevel) {
292		PyErr_Restore(exc_type, exc_value , exc_traceback);
293		NSLog(@"PyObjC: Converting exception to Objective-C:");
294		PyErr_Print();
295	} else {
296		Py_DECREF(exc_type);
297		Py_XDECREF(exc_value);
298		Py_XDECREF(exc_traceback);
299	}
300	return val;
301}
302
303void
304PyObjCErr_ToObjCWithGILState(PyGILState_STATE* state)
305{
306	NSException* exc = PyObjCErr_AsExc();
307
308	if (state) {
309		PyGILState_Release(*state);
310	}
311	[exc raise];
312
313	/* Fatal error: this should never happen */
314	abort();
315}
316
317
318char*
319PyObjCUtil_Strdup(const char* value)
320{
321	Py_ssize_t len;
322	char* result;
323
324	len = strlen(value);
325	result = PyMem_Malloc(len+1);
326	if (result == NULL) return NULL;
327
328	memcpy(result, value, len);
329	result[len] = 0;
330	return result;
331}
332
333
334NSMapTableKeyCallBacks PyObjCUtil_PointerKeyCallBacks = {
335	NULL,
336	NULL,
337	NULL,
338	NULL,
339	NULL,
340	NULL,
341};
342
343NSMapTableValueCallBacks PyObjCUtil_PointerValueCallBacks = {
344	NULL,
345	NULL,
346	NULL,
347};
348
349static void
350nsmaptable_objc_retain(NSMapTable *table __attribute__((__unused__)), const void *datum) {
351	CFRetain((id)datum);
352}
353
354static void
355nsmaptable_objc_release(NSMapTable *table __attribute__((__unused__)), void *datum) {
356	CFRelease((id)datum);
357}
358
359NSMapTableKeyCallBacks PyObjCUtil_ObjCIdentityKeyCallBacks = {
360	NULL,
361	NULL,
362	&nsmaptable_objc_retain,
363	&nsmaptable_objc_release,
364	NULL,
365	NULL,
366};
367
368NSMapTableValueCallBacks PyObjCUtil_ObjCValueCallBacks = {
369	&nsmaptable_objc_retain,
370	&nsmaptable_objc_release,
371	NULL  // generic description
372};
373
374
375#define SHOULD_FREE 1
376#define SHOULD_IGNORE 2
377
378void
379PyObjC_FreeCArray(int code, void* array)
380{
381	if (code == SHOULD_FREE) {
382		PyMem_Free(array);
383	}
384}
385
386static PyTypeObject* array_type = NULL;
387
388static inline PyTypeObject*
389fetch_array_type(void)
390{
391	PyObject* mod;
392	PyObject* name;
393
394	if (array_type != NULL) return array_type;
395
396	name = PyText_FromString("array");
397	if (name == NULL) {
398		return NULL;
399	}
400
401	mod = PyImport_Import(name);
402	Py_DECREF(name);
403	if (mod == NULL) {
404		return NULL;
405	}
406
407	array_type = (PyTypeObject*)PyObject_GetAttrString(mod, "ArrayType");
408	Py_DECREF(mod);
409	if (array_type == NULL) {
410		return NULL;
411	}
412
413	/* XXX: check if array_type is realy a type! */
414
415	return array_type;
416}
417
418#define array_check(obj) PyObject_TypeCheck(obj, fetch_array_type())
419
420static char
421array_typestr(PyObject* array)
422{
423	PyObject* typecode;
424	PyObject* bytes;
425	char res;
426
427	typecode = PyObject_GetAttrString(array, "typecode");
428	if (typecode == NULL) {
429		return '\0';
430	}
431
432	if (PyUnicode_Check(typecode)) {
433		bytes = PyUnicode_AsEncodedString(typecode, NULL, NULL);
434		if (bytes == NULL) {
435			return '\0';
436		}
437#if PY_MAJOR_VERSION == 2
438	} else if (PyString_Check(typecode)) {
439		bytes = typecode; Py_INCREF(bytes);
440#endif
441	} else {
442		PyErr_SetString(PyExc_TypeError, "typecode not a string");
443		return '\0';
444	}
445
446	switch (*PyBytes_AS_STRING(bytes)) {
447	case 'c': res = _C_CHR; break;
448	case 'b': res = _C_CHR; break;
449	case 'B': res = _C_UCHR; break;
450	case 'u': res = _C_SHT; break;
451	case 'h': res = _C_SHT; break;
452	case 'H': res = _C_USHT; break;
453	case 'i': res = _C_INT; break;
454	case 'I': res = _C_UINT; break;
455	case 'l': res = _C_LNG; break;
456	case 'L': res = _C_ULNG; break;
457	case 'f': res = _C_FLT; break;
458	case 'd': res = _C_DBL; break;
459	default:
460		PyErr_SetString(PyExc_TypeError, "unsupported typecode");
461		res = '\0';
462	}
463	Py_DECREF(typecode);
464	Py_DECREF(bytes);
465
466	return res;
467}
468
469static int
470buffer_get(BOOL writable, PyObject* obj, void** bufptr, Py_ssize_t* sizeptr)
471{
472	if (writable) {
473		return PyObject_AsWriteBuffer(obj, bufptr,  sizeptr);
474	} else {
475		return PyObject_AsReadBuffer(obj, (const void**)bufptr,  sizeptr);
476	}
477}
478
479static char struct_elem_code(const char* typestr);
480
481static char
482array_elem_code(const char* typestr)
483{
484	char res = '\0';
485	char tmp;
486
487	if (*typestr++ != _C_ARY_B) {
488		return '\0';
489	}
490	while (isdigit(*typestr)) typestr++;
491
492	if (*typestr == _C_ARY_E) {
493		return '\0';
494	}
495
496	while (typestr && *typestr != _C_ARY_E) {
497		switch(*typestr) {
498		case _C_ARY_B:
499			tmp = array_elem_code(typestr);
500			if (tmp == '\0') return '\0';
501			if (res == '\0') {
502				res = tmp;
503			} else if (tmp != res) {
504				return '\0';
505			}
506			break;
507		case _C_STRUCT_B:
508			tmp = struct_elem_code(typestr);
509			if (tmp == '\0') return '\0';
510			if (res == '\0') {
511				res = tmp;
512			} else if (tmp != res) {
513				return '\0';
514			}
515			break;
516		default:
517			if (res != '\0' && *typestr != res) return '\0';
518			res = *typestr;
519		}
520
521		typestr = PyObjCRT_SkipTypeSpec(typestr);
522	}
523	return res;
524}
525
526static char
527struct_elem_code(const char* typestr)
528{
529	char res = '\0';
530	char tmp;
531
532	if (*typestr++ != _C_STRUCT_B) {
533		return '\0';
534	}
535
536	while (*typestr != '=' && *typestr != _C_STRUCT_E) {
537		typestr++;
538	}
539
540	if (*typestr == _C_STRUCT_E) {
541		return '\0';
542	}
543	typestr++;
544
545	while (typestr && *typestr != _C_STRUCT_E) {
546		switch(*typestr) {
547		case _C_ARY_B:
548			tmp = array_elem_code(typestr);
549			if (tmp == '\0') return '\0';
550			if (res == '\0') {
551				res = tmp;
552			} else if (tmp != res) {
553				return '\0';
554			}
555			break;
556		case _C_STRUCT_B:
557			tmp = struct_elem_code(typestr);
558			if (tmp == '\0') return '\0';
559			if (res == '\0') {
560				res = tmp;
561			} else if (tmp != res) {
562				return '\0';
563			}
564			break;
565		default:
566			if (res != '\0' && *typestr != res) return '\0';
567			res = *typestr;
568		}
569
570		typestr = PyObjCRT_SkipTypeSpec(typestr);
571	}
572	return res;
573}
574
575static BOOL
576code_compatible(char array_code, char type_code)
577{
578	if (array_code == type_code) {
579		return YES;
580	}
581	switch (type_code) {
582	case _C_LNG_LNG:
583#ifdef __LP64__
584		/* fall through */
585#else
586		return NO;
587#endif
588	case _C_LNG:
589		return (array_code == 'l')
590#ifndef __LP64__
591			|| (array_code == 'i')
592#endif
593		;
594	case _C_ULNG_LNG:
595#ifdef __LP64__
596		/* fall through */
597#else
598		return NO;
599#endif
600	case _C_ULNG:
601		return (array_code == 'L')
602#ifndef __LP64__
603			|| (array_code == 'I')
604#endif
605		;
606
607	case _C_INT:
608		return (array_code == 'i')
609#ifndef __LP64__
610			|| (array_code == 'l')
611#endif
612		;
613	case _C_UINT:
614		return (array_code == 'I')
615#ifndef __LP64__
616			|| (array_code == 'L')
617#endif
618		;
619
620	case _C_NSBOOL:
621		return (array_code == _C_CHR) || (array_code == _C_UCHR);
622	case _C_CHAR_AS_INT:
623		return (array_code == _C_CHR) || (array_code == _C_UCHR);
624	case _C_CHAR_AS_TEXT:
625		return (array_code == _C_CHR);
626	case _C_UNICHAR:
627		return (array_code == _C_SHT);
628	}
629	return NO;
630}
631
632
633/*
634 * Convert a Python object to an array of 'elementType'. The array should
635 * contain 'pythonCount' elements, Py_None or NULL is accepted and will result
636 * in converting the entire Python sequence.
637 *
638 * The pythonList should either be a python sequence with appropriate entries,
639 * an array.array whose element-types match the element-types of the
640 * 'elementType' or an appropriatly typed and shaped numeric array.
641 *
642 * XXX: Numeric arrays are not yet supported.
643 * XXX: Unicode arrays are not yet support (_C_UNICHAR)
644 */
645int
646PyObjC_PythonToCArray(
647	BOOL        writable, BOOL exactSize,
648	const char* elementType,
649	PyObject*   pythonList,
650	void** array,
651	Py_ssize_t*   size,
652	PyObject**    bufobj)
653{
654	Py_ssize_t eltsize = PyObjCRT_SizeOfType(elementType);
655	Py_ssize_t i;
656	int r;
657
658
659	if (eltsize == -1) {
660		return -1;
661	}
662
663	if ((eltsize == 1 || eltsize == 0) &&
664		!(*elementType == _C_NSBOOL || *elementType == _C_BOOL || *elementType == _C_CHAR_AS_INT)) {
665		/* A simple byte-array */
666		/* Note: PyUnicode is explicitly excluded because it
667		 * implemenents the character buffer interface giving access
668		 * to the raw implementation. That's almost always not want
669		 * you want.
670		 */
671		char* buf;
672		Py_ssize_t bufsize;
673		int have_buffer;
674
675		if (PyUnicode_Check(pythonList)) {
676			PyErr_Format(PyExc_TypeError,
677				"Expecting byte-buffer, got %s",
678				Py_TYPE(pythonList)->tp_name);
679			return -1;
680		}
681
682
683		have_buffer = buffer_get(writable, pythonList, (void**)&buf, &bufsize);
684		if (have_buffer == -1) {
685			if (writable) {
686				/* Ensure that the expected semantics still work
687				 * when the passed in buffer is read-only
688				 */
689				if (buffer_get(NO, pythonList, (void**)&buf, &bufsize) == -1) {
690					return -1;
691				}
692
693				if (size == NULL || *size == -1) {
694					*array = PyMem_Malloc(bufsize);
695					if (*array == NULL) {
696						return -1;
697					}
698					memcpy(*array, buf, bufsize);
699				} else {
700					if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) {
701						PyErr_Format(PyExc_ValueError,
702							"Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer "
703							"of %"PY_FORMAT_SIZE_T"d", *size, bufsize);
704						return -1;
705					}
706					*array = PyMem_Malloc(*size);
707					if (*array == NULL) {
708						return -1;
709					}
710					memcpy(*array, buf, *size);
711				}
712				return SHOULD_FREE;
713			}
714		}
715
716		if (have_buffer != -1) {
717			if (size == NULL) {
718				*array = buf;
719				*bufobj = pythonList;
720				Py_INCREF(pythonList);
721
722			} else if (*size == -1) {
723				*array = buf;
724				*size = bufsize;
725				*bufobj = pythonList;
726				Py_INCREF(pythonList);
727
728			} else {
729				if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) {
730					PyErr_Format(PyExc_ValueError,
731						"Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer "
732						"of %"PY_FORMAT_SIZE_T"d", *size, bufsize);
733					return -1;
734				}
735				*array = buf;
736				*bufobj = pythonList;
737				Py_INCREF(pythonList);
738			}
739			return SHOULD_IGNORE;
740		}
741
742		PyErr_Clear();
743	}
744
745	if (*elementType == _C_UNICHAR && PyUnicode_Check(pythonList)) {
746		Py_ssize_t bufsize = PyUnicode_GetSize(pythonList);
747
748		if (*size == -1) {
749			*size = bufsize;
750		} else if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) {
751			PyErr_Format(PyExc_ValueError,
752				"Requesting unicode buffer of %"PY_FORMAT_SIZE_T"d, have unicode buffer "
753				"of %"PY_FORMAT_SIZE_T"d", *size, bufsize);
754			return -1;
755		}
756
757#if PY_VERSION_HEX >= 0x03030000
758		*bufobj = _PyUnicode_EncodeUTF16(
759			pythonList, NULL,
760#ifdef WORDS_BIGENDIAN
761			1
762#else
763			-1
764#endif
765		);
766		if (*bufobj == NULL) {
767			return -1;
768		}
769
770		/* XXX: Update API protocol to make the extra copy not necessary
771		 * Cannot use the code at the end because 'buffer' is assumed to be
772		 * the value to return to the python caller.
773		 */
774		*array = PyMem_Malloc(PyBytes_Size(*bufobj));
775		memcpy(*array, PyBytes_AsString(*bufobj), PyBytes_Size(*bufobj));
776		Py_DECREF(*bufobj);
777		*bufobj = NULL;
778		return SHOULD_FREE;
779
780		/* *array = PyBytes_AsString(*bufobj); return SHOULD_IGNORE*/
781
782#else	/* Python before 3.3 */
783		if (writable) {
784			*array = PyMem_Malloc(*size * sizeof(UniChar));
785			memcpy(*array, PyUnicode_AsUnicode(pythonList), *size * sizeof(UniChar));
786			return SHOULD_FREE;
787		} else {
788			*array = PyUnicode_AsUnicode(pythonList);
789			*bufobj = pythonList;
790			Py_INCREF(pythonList);
791			return SHOULD_IGNORE;
792		}
793#endif  /* Python before 3.3 */
794#if PY_MAJOR_VERSION == 2
795	} else if (*elementType == _C_UNICHAR && PyString_Check(pythonList)) {
796		PyObject* u = PyUnicode_Decode(
797				PyString_AsString(pythonList),
798				PyString_Size(pythonList),
799				NULL, NULL);
800		if (u == NULL) {
801			return -1;
802		}
803
804		Py_ssize_t bufsize = PyUnicode_GetSize(u);
805
806		if (*size == -1) {
807			*size = bufsize;
808		} else if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) {
809			PyErr_Format(PyExc_ValueError,
810				"Requesting unicode buffer of %"PY_FORMAT_SIZE_T"d, have unicode buffer "
811				"of %"PY_FORMAT_SIZE_T"d", *size, bufsize);
812			Py_DECREF(u);
813			return -1;
814		}
815
816		if (writable) {
817			*array = PyMem_Malloc(*size * sizeof(UniChar));
818			memcpy(*array, PyUnicode_AsUnicode(u), *size * sizeof(UniChar));
819			Py_DECREF(u);
820			return SHOULD_FREE;
821		} else {
822			*array = PyUnicode_AsUnicode(u);
823			*bufobj = u;
824			return SHOULD_IGNORE;
825		}
826#endif
827	}
828
829	/* A more complex array */
830
831#if PY_VERSION_HEX >= 0x02060000
832	if (PyObject_CheckBuffer(pythonList)) {
833		/* An object that implements the new-style buffer interface.
834		 * Use the buffer interface description to check if the buffer
835		 * type is compatible with what we expect.
836		 *
837		 * Specifically:
838		 * - If the C code expects an array of basic types:
839		 *   the buffer must be a single-dimensional array of
840		 *   a compatible type.
841		 * - If the C code expects and array of structures:
842		 *   The python array must be two dimensional, one row
843		 *   in the python array corresponds to one struct "instance"
844		 * - If the C code expects a multi-dimensional array:
845		 *   the python buffer must have a compatible dimension.
846		 *
847		 * The array must be large enough and  mustn't contain holes
848		 * in the fragment that gets used by us.
849		 */
850
851	}
852
853#endif
854	if (array_check(pythonList)) {
855		/* An array.array. Only convert if the typestr describes an
856		 * simple type of the same type as the array, or a struct/array
857		 * containing only elements of the type of the array.
858		 */
859		char* buf;
860		Py_ssize_t bufsize;
861		char code = array_typestr(pythonList);
862		if (code_compatible(code, *elementType)) {
863			/* Simple array, ok */
864		} else if (*elementType == _C_ARY_B) {
865			/* Array of arrays, 'code' must be the same as the
866			 * element-type of the array.
867			 */
868			if (!code_compatible(code, array_elem_code(elementType))) {
869				PyErr_Format(PyExc_ValueError,
870					"type mismatch between array.array "
871					"of %c and and C array of %s",
872					code, elementType);
873				return -1;
874			}
875
876		} else if (*elementType == _C_STRUCT_B) {
877			/* Array of structs, 'code' must be the same as the
878			 * the field-types of the structs (that is, the struct
879			 * must contain one or more fields of type 'code').
880			 */
881			if (!code_compatible(code, struct_elem_code(elementType))) {
882				PyErr_Format(PyExc_ValueError,
883					"type mismatch between array.array "
884					"of %c and and C array of %s",
885					code, elementType);
886				return -1;
887			}
888		} else {
889			PyErr_Format(PyExc_ValueError,
890				"type mismatch between array.array "
891				"of %c and and C array of %s",
892				code, elementType);
893			return -1;
894		}
895
896		if (buffer_get(writable, pythonList, (void**)&buf, &bufsize) == -1) {
897			return -1;
898		}
899
900		assert(eltsize != 0);
901		if (eltsize == 0) {
902			PyErr_SetString(PyExc_ValueError, "array.array with elements without a size");
903			return -1;
904		}
905		if ((bufsize % eltsize) != 0) {
906			PyErr_SetString(PyExc_ValueError,
907					"Badly shaped array.array");
908			return -1;
909		}
910
911		*array = buf;
912
913		if (size == NULL) {
914			/* pass */
915
916		} else if (*size == -1) {
917			*size = bufsize / eltsize;
918
919		} else {
920			bufsize /= eltsize;
921
922			if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) {
923				PyErr_Format(PyExc_ValueError,
924					"Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer "
925					"of %"PY_FORMAT_SIZE_T"d", *size, bufsize);
926				return -1;
927			}
928			*array = buf;
929		}
930		*bufobj = pythonList;
931		Py_INCREF(pythonList);
932		return SHOULD_IGNORE;
933
934#ifdef PyObjC_ENABLE_NUMARRAY
935
936# error "Please implement Numarray/Numeric support"
937
938	} else if (...){
939		/* TODO: Convert the numeric array (or return a pointer to it's
940		 * data), but only if it is the right type:
941		 * - If typestr is a basic type, the array must be a 1D array
942		 *   of that type
943		 * - If typestr is a structured type, the array must be a 2D
944		 *   array where rows match the structured type
945		 *
946		 * XXX: I have no idea if this is feasable, not having used
947		 * numarray/numeric myself.
948		 */
949#endif /* PyObjC_ENABLE_NUMARRAY */
950	} else {
951		Py_ssize_t seqlen;
952		Py_ssize_t pycount;
953
954		if (*elementType == _C_NSBOOL) {
955			if (PyBytes_Check(pythonList)) {
956				PyErr_Format(PyExc_ValueError, "Need array of BOOL, got byte string");
957				return -1;
958			}
959		} else if (*elementType == _C_CHAR_AS_INT) {
960			if (PyBytes_Check(pythonList)) {
961				PyErr_Format(PyExc_ValueError, "Need array of small integers, got byte string");
962				return -1;
963			}
964		}
965		PyObject* seq = PySequence_Fast(pythonList,
966					"converting to a C array");
967		if (seq == NULL) {
968			return -1;
969		}
970
971		seqlen = PySequence_Fast_GET_SIZE(seq);
972		if (size == NULL || *size == -1) {
973			pycount = seqlen;
974		} else {
975			pycount = *size;
976		}
977
978		if ((exactSize && seqlen != pycount) || (!exactSize && seqlen < pycount)) {
979			Py_DECREF(seq);
980			PyErr_Format(PyExc_ValueError,
981					"too few values (%"PY_FORMAT_SIZE_T"d) expecting at "
982					"least %"PY_FORMAT_SIZE_T"d", seqlen, pycount);
983			return -1;
984		}
985		*array = PyMem_Malloc(eltsize * pycount);
986		if (*array == NULL) {
987			Py_DECREF(seq);
988			PyErr_NoMemory();
989			return -1;
990		}
991		if (size) {
992			*size = pycount;
993		}
994		*bufobj = NULL;
995
996		for (i = 0; i < pycount; i++) {
997			PyObject* item = PySequence_Fast_GET_ITEM(seq, i);
998
999			r = depythonify_c_value(elementType, item,
1000					((char*)*array)+(i*eltsize));
1001			if (r == -1) {
1002				Py_DECREF(seq);
1003				PyMem_Free(*array); *array = NULL;
1004				return -1;
1005			}
1006		}
1007		return SHOULD_FREE;
1008	}
1009
1010}
1011
1012
1013PyObject*
1014PyObjC_CArrayToPython(
1015	const char* elementType,
1016	void* array,
1017	Py_ssize_t size)
1018{
1019	PyObject* result;
1020	Py_ssize_t i;
1021	Py_ssize_t eltsize;
1022
1023	eltsize = PyObjCRT_SizeOfType(elementType);
1024	if (eltsize == -1) {
1025		return NULL;
1026	}
1027
1028
1029	if (eltsize == 1 || eltsize == 0) {
1030		if (*elementType == _C_CHAR_AS_TEXT) {
1031			return PyBytes_FromStringAndSize(array, size);
1032		}
1033		if (*elementType != _C_NSBOOL && *elementType != _C_BOOL && *elementType != _C_CHAR_AS_INT) {
1034			/* Special case for buffer-like objects */
1035			return PyBytes_FromStringAndSize(array, size);
1036		}
1037	}
1038
1039	if (*elementType == _C_UNICHAR) {
1040		int byteorder = 0;
1041		result = PyUnicode_DecodeUTF16(array, size*2, NULL, &byteorder);
1042		return result;
1043	}
1044
1045	result = PyTuple_New(size);
1046	if (result == NULL) {
1047		return NULL;
1048	}
1049
1050
1051	for (i = 0; i < size; i++) {
1052		PyObject* elt = pythonify_c_value(elementType, array);
1053		if (elt == NULL) {
1054			Py_DECREF(result);
1055			return NULL;
1056		}
1057
1058		PyTuple_SET_ITEM(result, i, elt);
1059		array = ((char*)array) + eltsize;
1060	}
1061
1062	return result;
1063}
1064
1065int
1066PyObjC_IsPythonKeyword(const char* word)
1067{
1068	/*
1069	 * We cheat a little: this list only contains those keywords that
1070	 * are actually used in Cocoa.
1071	 *
1072	 * XXX: If we ever add the complete list here we should optimize
1073	 * this function.
1074	 */
1075	static const char* keywords[] = {
1076		"class",
1077		"raise",
1078		NULL
1079	};
1080	const char** cur;
1081
1082	for (cur = keywords; *cur != NULL; cur++) {
1083		if (strcmp(word, *cur) == 0) {
1084			return 1;
1085		}
1086	}
1087	return 0;
1088}
1089
1090int
1091PyObjCRT_SimplifySignature(const char* signature, char* buf, size_t buflen)
1092{
1093	const char* cur;
1094	const char* end;
1095	const char* next;
1096
1097	cur = signature;
1098	*buf = '\0';
1099
1100	while (*cur != '\0') {
1101		next = end = PyObjCRT_SkipTypeSpec(cur);
1102		end -= 1;
1103		while (end != cur && isdigit(*end)) {
1104			end --;
1105		}
1106		end++;
1107
1108		if ((size_t)(end - cur) > buflen) {
1109			return -1;
1110		}
1111
1112		memcpy(buf, cur, end-cur);
1113		buflen -= (end-cur);
1114		buf += (end-cur);
1115		*buf = '\0';
1116		cur = next;
1117	}
1118	return 0;
1119}
1120
1121
1122PyObject*
1123PyObjC_CArrayToPython2(
1124	const char* elementType,
1125	void* array,
1126	Py_ssize_t size,
1127	bool alreadyRetained,
1128	bool alreadyCFRetained)
1129{
1130	PyObject* result;
1131	Py_ssize_t i;
1132	Py_ssize_t eltsize;
1133
1134	if (size == -1) {
1135		size = 0;
1136	}
1137
1138	eltsize = PyObjCRT_SizeOfType(elementType);
1139	if (eltsize == -1) {
1140		return NULL;
1141	}
1142
1143	if (eltsize == 1 || eltsize == 0) {
1144		if (*elementType == _C_CHAR_AS_TEXT) {
1145			return PyBytes_FromStringAndSize(array, size);
1146		}
1147		if (*elementType != _C_NSBOOL && *elementType != _C_BOOL && *elementType != _C_CHAR_AS_INT) {
1148			/* Special case for buffer-like objects */
1149			return PyBytes_FromStringAndSize(array, size);
1150		}
1151	}
1152	if (*elementType == _C_UNICHAR) {
1153		int byteorder = 0;
1154		result = PyUnicode_DecodeUTF16(array, size*2, NULL, &byteorder);
1155		return result;
1156	}
1157
1158	result = PyTuple_New(size);
1159	if (result == NULL) {
1160		return NULL;
1161	}
1162
1163
1164	for (i = 0; i < size; i++) {
1165		PyObject* elt = pythonify_c_value(elementType, array);
1166		if (elt == NULL) {
1167			Py_DECREF(result);
1168			return NULL;
1169		}
1170
1171		if (alreadyRetained) {
1172			[*(id*)array release];
1173		} else if (alreadyCFRetained) {
1174			CFRelease(*(id*)array);
1175		}
1176
1177		PyTuple_SET_ITEM(result, i, elt);
1178		array = ((char*)array) + eltsize;
1179	}
1180
1181	return result;
1182}
1183
1184int
1185PyObjCObject_Convert(PyObject* object, void* pvar)
1186{
1187	int r;
1188	r = depythonify_c_value(@encode(id), object, (id*)pvar);
1189	if (r == -1) {
1190		return 0;
1191	} else {
1192		return 1;
1193	}
1194}
1195
1196int
1197PyObjCClass_Convert(PyObject* object, void* pvar)
1198{
1199    if (!PyObjCClass_Check(object)) {
1200        PyErr_SetString(PyExc_TypeError, "Expected objective-C class");
1201        return 0;
1202    }
1203
1204    *(Class*)pvar = PyObjCClass_GetClass(object);
1205    if (*(Class*)pvar == NULL) return 0;
1206    return 1;
1207}
1208
1209int PyObjC_is_ascii_string(PyObject* unicode_string, const char* ascii_string)
1210{
1211#if PY_MAJOR_VERSION == 2
1212	if (PyString_Check(unicode_string)) {
1213		return strcmp(PyString_AsString(unicode_string), ascii_string) == 0;
1214	} else {
1215#endif
1216
1217	size_t uni_sz = PyUnicode_GetSize(unicode_string);
1218	size_t i;
1219	Py_UNICODE* code_points = PyUnicode_AsUnicode(unicode_string);
1220
1221	if (code_points == NULL) {
1222		PyErr_Clear();
1223		return 0;
1224	}
1225
1226	for (i = 0; i < uni_sz; i++) {
1227		if (code_points[i] != (Py_UNICODE)ascii_string[i]) {
1228			return 0;
1229		} else if (ascii_string[i] == '\0') {
1230			return 0;
1231		}
1232	}
1233	if (ascii_string[i] != '\0') {
1234		return 0;
1235	}
1236	return 1;
1237#if PY_MAJOR_VERSION == 2
1238	}
1239#endif
1240}
1241
1242int PyObjC_is_ascii_prefix(PyObject* unicode_string, const char* ascii_string, size_t n)
1243{
1244	size_t uni_sz = PyUnicode_GetSize(unicode_string);
1245	size_t i;
1246	Py_UNICODE* code_points = PyUnicode_AsUnicode(unicode_string);
1247
1248	if (code_points == NULL) {
1249		PyErr_Clear();
1250		return 0;
1251	}
1252
1253	for (i = 0; i < uni_sz && i < n; i++) {
1254		if (code_points[i] != (Py_UNICODE)ascii_string[i]) {
1255			return 0;
1256		} else if (ascii_string[i] == '\0') {
1257			return 0;
1258		}
1259	}
1260	return 1;
1261}
1262
1263PyObject*
1264PyObjC_ImportName(const char* name)
1265{
1266	PyObject* py_name;
1267	PyObject* mod;
1268	char* c = strrchr(name, '.');
1269
1270	if (c == NULL) {
1271		/* Toplevel module */
1272		py_name = PyText_FromString(name);
1273		mod = PyImport_Import(py_name);
1274		Py_DECREF(py_name);
1275		return mod;
1276	} else {
1277		py_name = PyText_FromStringAndSize(name, c - name);
1278		mod = PyImport_Import(py_name);
1279		Py_DECREF(py_name);
1280		if (mod == NULL) {
1281			return NULL;
1282		}
1283
1284		PyObject* v = PyObject_GetAttrString(mod, c + 1);
1285		Py_DECREF(mod);
1286		return v;
1287	}
1288}
1289