1/*
2 * Implements a function to fetch the list of objective-C classes known
3 * in the runtime.
4 */
5#include "pyobjc.h"
6
7
8	/* Implementation for MacOS X */
9
10Py_ssize_t
11PyObjC_ClassCount(void)
12{
13	int neededLen = objc_getClassList(NULL, 0);
14	return neededLen;
15}
16
17
18PyObject*
19PyObjC_GetClassList(void)
20{
21	PyObject* 	result = NULL;
22	Class*		buffer = NULL;
23	int		bufferLen = 0;
24	int		neededLen = 0;
25	int             i;
26
27	/*
28	 * objc_getClassList returns the number of classes known in the runtime,
29	 * the documented way to fetch the list is:
30	 * 1. call ret = objc_getClassList(NULL, 0);
31	 * 2. allocate a buffer of 'ret' class-pointers
32	 * 3. call objc_getClassList again with this buffer.
33	 *
34	 * Step 3 might return more classes because another thread may have
35	 * loaded a new framework/bundle. This means we need a loop to be sure
36	 * we'll get all classes.
37	 */
38	neededLen = objc_getClassList(NULL, 0);
39	bufferLen = 0;
40	buffer = NULL;
41
42	while (bufferLen < neededLen) {
43		Class*    newBuffer;
44		bufferLen = neededLen;
45
46		/* Realloc(NULL, ...) might not work, call Malloc when
47		 * the buffer is NULL.
48		 */
49		if (buffer == NULL) {
50			newBuffer = PyMem_Malloc(
51				sizeof(Class) * bufferLen);
52		} else {
53			newBuffer = PyMem_Realloc(buffer,
54				sizeof(Class) * bufferLen);
55		}
56		if (newBuffer == NULL) {
57			PyErr_NoMemory();
58			goto error;
59		}
60		buffer = newBuffer; newBuffer = NULL;
61		neededLen = objc_getClassList(buffer, bufferLen);
62	}
63	bufferLen = neededLen;
64
65	result = PyTuple_New(bufferLen);
66	if (result == NULL) {
67		goto error;
68	}
69
70	for (i = 0; i < bufferLen; i++) {
71		PyObject* pyclass;
72
73		pyclass = PyObjCClass_New(buffer[i]);
74		if (pyclass == NULL) {
75			goto error;
76		}
77		PyTuple_SET_ITEM(result, i, pyclass);
78	}
79
80	PyMem_Free(buffer); buffer = NULL;
81
82	return result;
83
84error:
85	if (buffer != NULL) {
86		PyMem_Free(buffer);
87		buffer = NULL;
88	}
89	Py_XDECREF(result);
90	return NULL;
91}
92