summaryrefslogtreecommitdiff
path: root/c/file_emulator.h
diff options
context:
space:
mode:
Diffstat (limited to 'c/file_emulator.h')
-rw-r--r--c/file_emulator.h93
1 files changed, 93 insertions, 0 deletions
diff --git a/c/file_emulator.h b/c/file_emulator.h
new file mode 100644
index 0000000..82a34c0
--- /dev/null
+++ b/c/file_emulator.h
@@ -0,0 +1,93 @@
+
+/* Emulation of PyFile_Check() and PyFile_AsFile() for Python 3. */
+
+static PyObject *PyIOBase_TypeObj;
+
+static int init_file_emulator(void)
+{
+ if (PyIOBase_TypeObj == NULL) {
+ PyObject *io = PyImport_ImportModule("_io");
+ if (io == NULL)
+ return -1;
+ PyIOBase_TypeObj = PyObject_GetAttrString(io, "_IOBase");
+ if (PyIOBase_TypeObj == NULL)
+ return -1;
+ }
+ return 0;
+}
+
+
+#define PyFile_Check(p) PyObject_IsInstance(p, PyIOBase_TypeObj)
+
+
+static void _close_file_capsule(PyObject *ob_capsule)
+{
+ FILE *f = (FILE *)PyCapsule_GetPointer(ob_capsule, "FILE");
+ if (f != NULL)
+ fclose(f);
+}
+
+
+static FILE *PyFile_AsFile(PyObject *ob_file)
+{
+ PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL;
+ FILE *f;
+ int fd;
+ const char *mode;
+
+ ob = PyObject_CallMethod(ob_file, "flush", NULL);
+ if (ob == NULL)
+ goto fail;
+ Py_DECREF(ob);
+
+ ob_capsule = PyObject_GetAttrString(ob_file, "__cffi_FILE");
+ if (ob_capsule == NULL) {
+ PyErr_Clear();
+
+ fd = PyObject_AsFileDescriptor(ob_file);
+ if (fd < 0)
+ goto fail;
+
+ ob_mode = PyObject_GetAttrString(ob_file, "mode");
+ if (ob_mode == NULL)
+ goto fail;
+ mode = PyText_AsUTF8(ob_mode);
+ if (mode == NULL)
+ goto fail;
+
+ fd = dup(fd);
+ if (fd < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto fail;
+ }
+
+ f = fdopen(fd, mode);
+ if (f == NULL) {
+ close(fd);
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto fail;
+ }
+ setbuf(f, NULL); /* non-buffered */
+ Py_DECREF(ob_mode);
+ ob_mode = NULL;
+
+ ob_capsule = PyCapsule_New(f, "FILE", _close_file_capsule);
+ if (ob_capsule == NULL) {
+ fclose(f);
+ goto fail;
+ }
+
+ if (PyObject_SetAttrString(ob_file, "__cffi_FILE", ob_capsule) < 0)
+ goto fail;
+ }
+ else {
+ f = PyCapsule_GetPointer(ob_capsule, "FILE");
+ }
+ Py_DECREF(ob_capsule); /* assumes still at least one reference */
+ return f;
+
+ fail:
+ Py_XDECREF(ob_mode);
+ Py_XDECREF(ob_capsule);
+ return NULL;
+}