1#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
2
3static void* 
4mod_filedescr_retain(void* info) 
5{
6	PyGILState_STATE state = PyGILState_Ensure();
7	Py_INCREF((PyObject*)info);
8	PyGILState_Release(state);
9	return info;
10}
11
12static void
13mod_filedescr_release(void* info)
14{
15	PyGILState_STATE state = PyGILState_Ensure();
16	Py_DECREF((PyObject*)info);
17	PyGILState_Release(state);
18}
19
20
21static CFFileDescriptorContext mod_CFFileDescriptorContext = {
22	0,		
23	NULL,
24	mod_filedescr_retain,
25	mod_filedescr_release,
26	NULL
27};
28
29static void
30mod_CFFileDescriptorCallBack(	
31	CFFileDescriptorRef f,
32	CFOptionFlags callBackType,
33	void* _info)
34{
35	PyObject* info = (PyObject*)_info;
36	PyGILState_STATE state = PyGILState_Ensure();
37
38	PyObject* py_f = PyObjC_ObjCToPython(@encode(CFFileDescriptorRef), &f);
39	PyObject* py_callBackType = PyObjC_ObjCToPython(
40		@encode(CFOptionFlags), &callBackType);
41
42	PyObject* result = PyObject_CallFunction(
43		PyTuple_GET_ITEM(info, 0),
44		"NNO", py_f, py_callBackType, PyTuple_GET_ITEM(info, 1));
45	if (result == NULL) {
46		PyObjCErr_ToObjCWithGILState(&state);
47	}
48	Py_DECREF(result);
49	PyGILState_Release(state);
50}
51
52static PyObject*
53mod_CFFileDescriptorCreate(
54	PyObject* self __attribute__((__unused__)),
55	PyObject* args)
56{
57	PyObject* py_allocator;
58	PyObject* py_descriptor;
59	PyObject* py_closeOnInvalidate;
60	PyObject* callout;
61	PyObject* info;
62	CFAllocatorRef allocator;
63	CFFileDescriptorNativeDescriptor descriptor;
64	Boolean closeOnInvalidate;
65
66	if (!PyArg_ParseTuple(args, "OOOOO", &py_allocator, &py_descriptor, &py_closeOnInvalidate, &callout, &info)) {
67		return NULL;
68	}
69
70	if (PyObjC_PythonToObjC(@encode(CFAllocatorRef), py_allocator, &allocator) < 0) {
71		return NULL;
72	}
73	if (PyObjC_PythonToObjC(@encode(CFFileDescriptorNativeDescriptor), py_descriptor, &descriptor) < 0) {
74		return NULL;
75	}
76	if (PyObjC_PythonToObjC(@encode(bool), py_closeOnInvalidate, &closeOnInvalidate) < 0) {
77		return NULL;
78	}
79
80	CFFileDescriptorContext context = mod_CFFileDescriptorContext;
81	context.info = Py_BuildValue("OO", callout, info);
82	if (context.info == NULL) {
83		return NULL;
84	}
85
86	CFFileDescriptorRef rv = NULL;
87	PyObjC_DURING
88		rv = CFFileDescriptorCreate(
89			allocator, descriptor, closeOnInvalidate,
90			mod_CFFileDescriptorCallBack, &context);
91		
92
93	PyObjC_HANDLER
94		rv = NULL;
95		PyObjCErr_FromObjC(localException);
96
97	PyObjC_ENDHANDLER
98
99	Py_DECREF((PyObject*)context.info);
100	if (PyErr_Occurred()) {
101		return NULL;
102	}
103
104	PyObject* result =  PyObjC_ObjCToPython(@encode(CFFileDescriptorRef), &rv);
105	if (rv != NULL) {
106		CFRelease(rv);
107	}
108	return result;
109}
110
111
112static PyObject*
113mod_CFFileDescriptorGetContext(
114	PyObject* self __attribute__((__unused__)),
115	PyObject* args)
116{
117	PyObject* py_f;
118	PyObject* py_context;
119	CFFileDescriptorRef f;
120	CFFileDescriptorContext context;
121
122	if (!PyArg_ParseTuple(args, "OO", &py_f, &py_context)) {
123		return NULL;
124	}
125
126	if (py_context != Py_None) {
127		PyErr_SetString(PyExc_ValueError, "invalid context");
128		return NULL;
129	}
130
131	if (PyObjC_PythonToObjC(@encode(CFFileDescriptorRef), py_f, &f) < 0) {
132		return NULL;
133	}
134
135	context.version = 0;
136
137	PyObjC_DURING
138		CFFileDescriptorGetContext(f, &context);
139
140	PyObjC_HANDLER
141		PyObjCErr_FromObjC(localException);
142
143	PyObjC_ENDHANDLER
144
145	if (PyErr_Occurred()) {
146		return NULL;
147	}
148
149	if (context.version != 0) {
150		PyErr_SetString(PyExc_ValueError, "retrieved context is not valid");
151		return NULL;
152	}
153
154	if (context.retain != mod_filedescr_retain) {
155		PyErr_SetString(PyExc_ValueError, 
156			"retrieved context is not supported");
157		return NULL;
158	}
159
160	Py_INCREF(PyTuple_GET_ITEM((PyObject*)context.info, 1));
161	return PyTuple_GET_ITEM((PyObject*)context.info, 1);
162}
163#endif
164
165#define COREFOUNDATION_FILEDESCRIPTOR_METHODS		\
166        {		\
167		"CFFileDescriptorCreate",		\
168		(PyCFunction)mod_CFFileDescriptorCreate,		\
169		METH_VARARGS,		\
170		NULL		\
171	},		\
172        {		\
173		"CFFileDescriptorGetContext",		\
174		(PyCFunction)mod_CFFileDescriptorGetContext,		\
175		METH_VARARGS,		\
176		NULL		\
177	},
178