/* ------------------------------------------------------------------------- */ /* * Copyright 2007-2023 GRAHAM DUMPLETON * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* ------------------------------------------------------------------------- */ #include "wsgi_stream.h" /* ------------------------------------------------------------------------- */ PyTypeObject Stream_Type; static PyObject *Stream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { StreamObject *self; self = (StreamObject *)type->tp_alloc(type, 0); if (self == NULL) return NULL; self->filelike = Py_None; Py_INCREF(self->filelike); self->blksize = 0; return (PyObject *)self; } static int Stream_init(StreamObject *self, PyObject *args, PyObject *kwds) { PyObject *filelike = NULL; apr_size_t blksize = HUGE_STRING_LEN; static char *kwlist[] = { "filelike", "blksize", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|l:FileWrapper", kwlist, &filelike, &blksize)) { return -1; } if (filelike) { PyObject *tmp = NULL; tmp = self->filelike; Py_INCREF(filelike); self->filelike = filelike; Py_XDECREF(tmp); } self->blksize = blksize; return 0; } static void Stream_dealloc(StreamObject *self) { Py_XDECREF(self->filelike); Py_TYPE(self)->tp_free(self); } static PyObject *Stream_iter(StreamObject *self) { Py_INCREF(self); return (PyObject *)self; } static PyObject *Stream_iternext(StreamObject *self) { PyObject *attribute = NULL; PyObject *method = NULL; PyObject *args = NULL; PyObject *result = NULL; attribute = PyObject_GetAttrString((PyObject *)self, "filelike"); if (!attribute) { PyErr_SetString(PyExc_KeyError, "file wrapper no filelike attribute"); return 0; } method = PyObject_GetAttrString(attribute, "read"); if (!method) { PyErr_SetString(PyExc_KeyError, "file like object has no read() method"); Py_DECREF(attribute); return 0; } Py_DECREF(attribute); attribute = PyObject_GetAttrString((PyObject *)self, "blksize"); if (!attribute) { PyErr_SetString(PyExc_KeyError, "file wrapper has no blksize attribute"); Py_DECREF(method); return 0; } if (!PyLong_Check(attribute)) { PyErr_SetString(PyExc_KeyError, "file wrapper blksize attribute not integer"); Py_DECREF(method); Py_DECREF(attribute); return 0; } args = Py_BuildValue("(O)", attribute); result = PyObject_CallObject(method, args); Py_DECREF(args); Py_DECREF(method); Py_DECREF(attribute); if (!result) return 0; if (PyString_Check(result)) { if (PyString_Size(result) == 0) { PyErr_SetObject(PyExc_StopIteration, Py_None); Py_DECREF(result); return 0; } return result; } Py_DECREF(result); PyErr_SetString(PyExc_TypeError, "file like object yielded non string type"); return 0; } static PyObject *Stream_close(StreamObject *self, PyObject *args) { PyObject *method = NULL; PyObject *result = NULL; if (!self->filelike || self->filelike == Py_None) { Py_INCREF(Py_None); return Py_None; } method = PyObject_GetAttrString(self->filelike, "close"); if (method) { result = PyObject_CallObject(method, (PyObject *)NULL); if (!result) PyErr_Clear(); Py_DECREF(method); } Py_XDECREF(result); Py_DECREF(self->filelike); self->filelike = NULL; Py_INCREF(Py_None); return Py_None; } static PyObject *Stream_get_filelike(StreamObject *self, void *closure) { Py_INCREF(self->filelike); return self->filelike; } static PyObject *Stream_get_blksize(StreamObject *self, void *closure) { return PyLong_FromLong(self->blksize); } static PyMethodDef Stream_methods[] = { { "close", (PyCFunction)Stream_close, METH_NOARGS, 0 }, { NULL, NULL } }; static PyGetSetDef Stream_getset[] = { { "filelike", (getter)Stream_get_filelike, NULL, 0 }, { "blksize", (getter)Stream_get_blksize, NULL, 0 }, { NULL }, }; PyTypeObject Stream_Type = { PyVarObject_HEAD_INIT(NULL, 0) "mod_wsgi.FileWrapper", /*tp_name*/ sizeof(StreamObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)Stream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ #if defined(Py_TPFLAGS_HAVE_ITER) Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ #endif 0, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ (getiterfunc)Stream_iter, /*tp_iter*/ (iternextfunc)Stream_iternext, /*tp_iternext*/ Stream_methods, /*tp_methods*/ 0, /*tp_members*/ Stream_getset, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ (initproc)Stream_init, /*tp_init*/ 0, /*tp_alloc*/ Stream_new, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ }; /* ------------------------------------------------------------------------- */ /* vi: set sw=4 expandtab : */