Browse Source

Add IoOut type to libpyfcgi

Yann Weber 4 years ago
parent
commit
8c69cd1b2f
2 changed files with 307 additions and 87 deletions
  1. 45
    19
      include/python_ioin.h
  2. 262
    68
      src/python_ioin.c

+ 45
- 19
include/python_ioin.h View File

41
 #include <limits.h>
41
 #include <limits.h>
42
 #include <stdlib.h>
42
 #include <stdlib.h>
43
 
43
 
44
+typedef int (*write_f)(const char*, size_t);
45
+
44
 #define IoIn__FromString(self, str) \
46
 #define IoIn__FromString(self, str) \
45
-(((IoIn*)self)->bin?PyBytes_FromString:PyUnicode_FromString)(str)
47
+(((PyIO_t*)self)->bin?PyBytes_FromString:PyUnicode_FromString)(str)
46
 
48
 
47
-#define IoIn__FromBuff(self) IoIn__FromString(self, ((IoIn*)self)->buff)
49
+#define IoIn__FromBuff(self) IoIn__FromString(self, ((PyIO_t*)self)->buff)
48
 
50
 
49
 extern PyMethodDef IoIn_methods[];
51
 extern PyMethodDef IoIn_methods[];
50
 extern PyMemberDef IoIn_members[];
52
 extern PyMemberDef IoIn_members[];
51
 extern PyTypeObject IoInType;
53
 extern PyTypeObject IoInType;
52
 
54
 
55
+extern PyMethodDef IoOut_methods[];
56
+extern PyMemberDef IoOut_members[];
57
+extern PyTypeObject IoOutType;
58
+
53
 typedef struct
59
 typedef struct
54
 {
60
 {
55
 	PyObject_VAR_HEAD;
61
 	PyObject_VAR_HEAD;
56
 	PyObject *closed;
62
 	PyObject *closed;
57
-	FCGX_Stream **in_stream;
63
+	FCGX_Stream **io_stream;
58
 	char *buff;
64
 	char *buff;
59
 	/**@brief buffer size */
65
 	/**@brief buffer size */
60
 	int buff_sz;
66
 	int buff_sz;
62
 	short bin;
68
 	short bin;
63
 	/**@brief 1 if EOF encountered, else 0 */
69
 	/**@brief 1 if EOF encountered, else 0 */
64
 	short eof;
70
 	short eof;
65
-} IoIn;
66
 
71
 
72
+	write_f write;
73
+} PyIO_t;
74
+
75
+int pyfcgi_io_init(PyObject *self);
67
 int pyfcgi_ioin_init(PyObject *self, PyObject *args, PyObject *kwds);
76
 int pyfcgi_ioin_init(PyObject *self, PyObject *args, PyObject *kwds);
68
-void pyfcgi_ioin_del(IoIn *self);
77
+int pyfcgi_ioout_init(PyObject *self, PyObject *args, PyObject *kwds);
78
+
79
+void pyfcgi_io_del(PyIO_t *self);
80
+
81
+PyObject* pyfcgi_io_close(PyObject *self, PyObject **argv, Py_ssize_t argc);
82
+PyObject* pyfcgi_io_fileno(PyObject *self, PyObject **argv, Py_ssize_t argc);
83
+PyObject* pyfcgi_io_flush(PyObject *self, PyObject **argv, Py_ssize_t argc);
84
+
85
+PyObject* pyfcgi_io_truncate(PyObject *self, PyObject **argv, Py_ssize_t argc);
86
+PyObject* pyfcgi_io_seekable(PyObject *self, PyObject **argv, Py_ssize_t argc);
87
+#define pyfcgi_io_seekable pyfcgi_io_false
88
+#define pyfcgi_io_isatty pyfcgi_io_false
89
+
90
+PyObject* pyfcgi_io_SeekError(PyObject *self, PyObject **argv, Py_ssize_t argc);
91
+#define pyfcgi_io_seek pyfcgi_io_SeekError
92
+#define pyfcgi_io_tell pyfcgi_io_SeekError
93
+
94
+PyObject* pyfcgi_io_WriteError(PyObject *self, PyObject **argv, Py_ssize_t argc);
95
+PyObject* pyfcgi_io_ReadError(PyObject *self, PyObject **argv, Py_ssize_t argc);
69
 
96
 
70
-PyObject* pyfcgi_ioin_close(PyObject *self, PyObject **argv, Py_ssize_t argc);
71
-PyObject* pyfcgi_ioin_fileno(PyObject *self, PyObject **argv, Py_ssize_t argc);
72
-PyObject* pyfcgi_ioin_flush(PyObject *self, PyObject **argv, Py_ssize_t argc);
73
-PyObject* pyfcgi_ioin_isatty(PyObject *self, PyObject **argv, Py_ssize_t argc);
74
-PyObject* pyfcgi_ioin_readable(PyObject *self, PyObject **argv, Py_ssize_t argc);
97
+#define pyfcgi_ioin_readable pyfcgi_io_true
75
 PyObject* pyfcgi_ioin_readline(PyObject *self, PyObject **argv, Py_ssize_t argc);
98
 PyObject* pyfcgi_ioin_readline(PyObject *self, PyObject **argv, Py_ssize_t argc);
76
 PyObject* pyfcgi_ioin_readlines(PyObject *self, PyObject **argv, Py_ssize_t argc);
99
 PyObject* pyfcgi_ioin_readlines(PyObject *self, PyObject **argv, Py_ssize_t argc);
77
 PyObject* pyfcgi_ioin_read(PyObject *self, PyObject **argv, Py_ssize_t argc);
100
 PyObject* pyfcgi_ioin_read(PyObject *self, PyObject **argv, Py_ssize_t argc);
78
 PyObject* pyfcgi_ioin_readall(PyObject *self, PyObject **argv, Py_ssize_t argc);
101
 PyObject* pyfcgi_ioin_readall(PyObject *self, PyObject **argv, Py_ssize_t argc);
79
 PyObject* pyfcgi_ioin_readinto(PyObject *self, PyObject **argv, Py_ssize_t argc);
102
 PyObject* pyfcgi_ioin_readinto(PyObject *self, PyObject **argv, Py_ssize_t argc);
80
 
103
 
81
-PyObject* pyfcgi_ioin_WriteError(PyObject *self, PyObject **argv, Py_ssize_t argc);
82
-#define pyfcgi_ioin_writelines pyfcgi_ioin_WriteError
83
-#define pyfcgi_ioin_write pyfcgi_ioin_WriteError
104
+#define pyfcgi_ioin_writable pyfcgi_io_true
105
+#define pyfcgi_ioin_writelines pyfcgi_io_WriteError
106
+#define pyfcgi_ioin_write pyfcgi_io_WriteError
84
 
107
 
85
-PyObject* pyfcgi_ioin_SeekError(PyObject *self, PyObject **argv, Py_ssize_t argc);
86
-#define pyfcgi_ioin_seek pyfcgi_ioin_SeekError
87
-#define pyfcgi_ioin_tell pyfcgi_ioin_SeekError
108
+#define pyfcgi_ioout_readable pyfcgi_io_false
109
+#define pyfcgi_ioout_readline pyfcgi_io_ReadError
110
+#define pyfcgi_ioout_readlines pyfcgi_io_ReadError
111
+#define pyfcgi_ioout_read pyfcgi_io_ReadError
112
+#define pyfcgi_ioout_readall pyfcgi_io_ReadError
113
+#define pyfcgi_ioout_readinto pyfcgi_io_ReadError
88
 
114
 
89
-PyObject* pyfcgi_ioin_truncate(PyObject *self, PyObject **argv, Py_ssize_t argc);
90
-PyObject* pyfcgi_ioin_seekable(PyObject *self, PyObject **argv, Py_ssize_t argc);
91
-PyObject* pyfcgi_ioin_writable(PyObject *self, PyObject **argv, Py_ssize_t argc);
115
+#define pyfcgi_ioout_writable pyfcgi_io_true
116
+PyObject* pyfcgi_ioout_writelines(PyObject *self, PyObject **argv, Py_ssize_t argc);
117
+PyObject* pyfcgi_ioout_write(PyObject *self, PyObject **argv, Py_ssize_t argc);
92
 
118
 
93
 #endif
119
 #endif

+ 262
- 68
src/python_ioin.c View File

3
  * @ingroup lib_ioin
3
  * @ingroup lib_ioin
4
  */
4
  */
5
 
5
 
6
-/**@brief If given object in_stream is NULL set error indicator
6
+/**@brief If given object io_stream is NULL set error indicator
7
  * @return 0 if no error else -1 or -2
7
  * @return 0 if no error else -1 or -2
8
  */
8
  */
9
 static int _check_nullin(PyObject *self);
9
 static int _check_nullin(PyObject *self);
14
  * @param int nreq number of bytes required in buffer
14
  * @param int nreq number of bytes required in buffer
15
  * @return 0 on error else buffer size
15
  * @return 0 on error else buffer size
16
  */
16
  */
17
-static int pyfcgi_ioin__reqbuf(PyObject *self, int nreq);
17
+static int pyfcgi_io__reqbuf(PyObject *self, int nreq);
18
 
18
 
19
 /**@brief Concat two bytes/unicode given IoIn configuration flag
19
 /**@brief Concat two bytes/unicode given IoIn configuration flag
20
  */
20
  */
21
 static PyObject* IoIn__Concat(PyObject *self, PyObject *left, PyObject *right);
21
 static PyObject* IoIn__Concat(PyObject *self, PyObject *left, PyObject *right);
22
 
22
 
23
+PyObject* pyfcgi_io_true(PyObject *self, PyObject **argv, Py_ssize_t argc);
24
+PyObject* pyfcgi_io_false(PyObject *self, PyObject **argv, Py_ssize_t argc);
25
+
23
 PyMethodDef IoIn_methods[] = {
26
 PyMethodDef IoIn_methods[] = {
24
-	{"close", (PyCFunction)pyfcgi_ioin_close, METH_FASTCALL, NULL},
25
-	{"fileno", (PyCFunction)pyfcgi_ioin_fileno, METH_FASTCALL, NULL},
26
-	{"flush", (PyCFunction)pyfcgi_ioin_flush, METH_FASTCALL, NULL},
27
-	{"isatty", (PyCFunction)pyfcgi_ioin_isatty, METH_FASTCALL, NULL},
27
+	{"close", (PyCFunction)pyfcgi_io_close, METH_FASTCALL, NULL},
28
+	{"fileno", (PyCFunction)pyfcgi_io_fileno, METH_FASTCALL, NULL},
29
+	{"flush", (PyCFunction)pyfcgi_io_flush, METH_FASTCALL, NULL},
30
+	{"isatty", (PyCFunction)pyfcgi_io_isatty, METH_FASTCALL, NULL},
28
 	{"readable", (PyCFunction)pyfcgi_ioin_readable, METH_FASTCALL, NULL},
31
 	{"readable", (PyCFunction)pyfcgi_ioin_readable, METH_FASTCALL, NULL},
29
 	{"readline", (PyCFunction)pyfcgi_ioin_readline, METH_FASTCALL, NULL},
32
 	{"readline", (PyCFunction)pyfcgi_ioin_readline, METH_FASTCALL, NULL},
30
 	{"readlines", (PyCFunction)pyfcgi_ioin_readlines, METH_FASTCALL, NULL},
33
 	{"readlines", (PyCFunction)pyfcgi_ioin_readlines, METH_FASTCALL, NULL},
31
-	{"seek", (PyCFunction)pyfcgi_ioin_seek, METH_FASTCALL, NULL},
32
-	{"seekable", (PyCFunction)pyfcgi_ioin_seekable, METH_FASTCALL, NULL},
33
-	{"tell", (PyCFunction)pyfcgi_ioin_tell, METH_FASTCALL, NULL},
34
-	{"truncate", (PyCFunction)pyfcgi_ioin_truncate, METH_FASTCALL, NULL},
34
+	{"seek", (PyCFunction)pyfcgi_io_seek, METH_FASTCALL, NULL},
35
+	{"seekable", (PyCFunction)pyfcgi_io_seekable, METH_FASTCALL, NULL},
36
+	{"tell", (PyCFunction)pyfcgi_io_tell, METH_FASTCALL, NULL},
37
+	{"truncate", (PyCFunction)pyfcgi_io_truncate, METH_FASTCALL, NULL},
35
 	{"writable", (PyCFunction)pyfcgi_ioin_writable, METH_FASTCALL, NULL},
38
 	{"writable", (PyCFunction)pyfcgi_ioin_writable, METH_FASTCALL, NULL},
36
 	{"writelines", (PyCFunction)pyfcgi_ioin_writelines, METH_FASTCALL, NULL},
39
 	{"writelines", (PyCFunction)pyfcgi_ioin_writelines, METH_FASTCALL, NULL},
37
 	{"read", (PyCFunction)pyfcgi_ioin_read, METH_FASTCALL, NULL},
40
 	{"read", (PyCFunction)pyfcgi_ioin_read, METH_FASTCALL, NULL},
42
 };
45
 };
43
 
46
 
44
 PyMemberDef IoIn_members[] = {
47
 PyMemberDef IoIn_members[] = {
45
-	{"closed", T_OBJECT, offsetof(IoIn, closed), READONLY, "True if the stream is closed"},
48
+	{"closed", T_OBJECT, offsetof(PyIO_t, closed), READONLY, "True if the stream is closed"},
46
 	{NULL}
49
 	{NULL}
47
 };
50
 };
48
 
51
 
49
 PyTypeObject IoInType = {
52
 PyTypeObject IoInType = {
50
 	PyVarObject_HEAD_INIT(NULL, 0)
53
 	PyVarObject_HEAD_INIT(NULL, 0)
51
 	"libpyfcgi.IoIn",                     /* tp_name */
54
 	"libpyfcgi.IoIn",                     /* tp_name */
52
-	sizeof(IoIn),                        /* tp_basicsize */
55
+	sizeof(PyIO_t),                        /* tp_basicsize */
53
 	0,                                               /* tp_itemsize */
56
 	0,                                               /* tp_itemsize */
54
-	(destructor)pyfcgi_ioin_del, /* tp_dealloc */
57
+	(destructor)pyfcgi_io_del, /* tp_dealloc */
55
 	0,                                               /* tp_print */
58
 	0,                                               /* tp_print */
56
 	0,                                               /* tp_getattr */
59
 	0,                                               /* tp_getattr */
57
 	0,                                               /* tp_setattr */
60
 	0,                                               /* tp_setattr */
88
 	0,                            /* tp_new */
91
 	0,                            /* tp_new */
89
 };
92
 };
90
 
93
 
94
+PyMethodDef IoOut_methods[] = {
95
+	{"close", (PyCFunction)pyfcgi_io_close, METH_FASTCALL, NULL},
96
+	{"fileno", (PyCFunction)pyfcgi_io_fileno, METH_FASTCALL, NULL},
97
+	{"flush", (PyCFunction)pyfcgi_io_flush, METH_FASTCALL, NULL},
98
+	{"isatty", (PyCFunction)pyfcgi_io_isatty, METH_FASTCALL, NULL},
99
+	{"readable", (PyCFunction)pyfcgi_ioout_readable, METH_FASTCALL, NULL},
100
+	{"readline", (PyCFunction)pyfcgi_ioout_readline, METH_FASTCALL, NULL},
101
+	{"readlines", (PyCFunction)pyfcgi_ioout_readlines, METH_FASTCALL, NULL},
102
+	{"seek", (PyCFunction)pyfcgi_io_seek, METH_FASTCALL, NULL},
103
+	{"seekable", (PyCFunction)pyfcgi_io_seekable, METH_FASTCALL, NULL},
104
+	{"tell", (PyCFunction)pyfcgi_io_tell, METH_FASTCALL, NULL},
105
+	{"truncate", (PyCFunction)pyfcgi_io_truncate, METH_FASTCALL, NULL},
106
+	{"writable", (PyCFunction)pyfcgi_ioout_writable, METH_FASTCALL, NULL},
107
+	{"writelines", (PyCFunction)pyfcgi_ioout_writelines, METH_FASTCALL, NULL},
108
+	{"read", (PyCFunction)pyfcgi_ioout_read, METH_FASTCALL, NULL},
109
+	{"readall", (PyCFunction)pyfcgi_ioout_readall, METH_FASTCALL, NULL},
110
+	{"readinto", (PyCFunction)pyfcgi_ioout_readinto, METH_FASTCALL, NULL},
111
+	{"write", (PyCFunction)pyfcgi_ioout_write, METH_FASTCALL, NULL},
112
+	{NULL} //Sentinel
113
+};
91
 
114
 
92
-int pyfcgi_ioin_init(PyObject *self, PyObject *args, PyObject *kwds)
115
+PyMemberDef IoOut_members[] = {
116
+	{"closed", T_OBJECT, offsetof(PyIO_t, closed), READONLY, "True if the stream is closed"},
117
+	{NULL}
118
+};
119
+
120
+PyTypeObject IoOutType = {
121
+	PyVarObject_HEAD_INIT(NULL, 0)
122
+	"libpyfcgi.IoOut",                     /* tp_name */
123
+	sizeof(PyIO_t),                        /* tp_basicsize */
124
+	0,                                               /* tp_itemsize */
125
+	(destructor)pyfcgi_io_del, /* tp_dealloc */
126
+	0,                                               /* tp_print */
127
+	0,                                               /* tp_getattr */
128
+	0,                                               /* tp_setattr */
129
+	0,                                               /* tp_reserved */
130
+	0,                                               /* tp_repr */
131
+	0,                                               /* tp_as_number */
132
+	0,                                               /* tp_as_sequence */
133
+	0,                              /* tp_as_mapping */
134
+	0,                                               /* tp_hash  */
135
+	0,                                               /* tp_call */
136
+	0,                                               /* tp_str */
137
+	0,                                               /* tp_getattro */
138
+	0,                                               /* tp_setattro */
139
+	0,                                               /* tp_as_buffer */
140
+	Py_TPFLAGS_DEFAULT |
141
+	Py_TPFLAGS_BASETYPE,   /* tp_flags */
142
+	"RawIo interface to FCGI input stream",                /* tp_doc */
143
+	0,                                               /* tp_traverse */
144
+	0,                                               /* tp_clear */
145
+	0,                                               /* tp_richcompare */
146
+	0,                                               /* tp_weaklistoffset */
147
+	0,                                               /* tp_iter */
148
+	0,                                               /* tp_iternext */
149
+	IoOut_methods,                        /* tp_methods */
150
+	IoOut_members,                        /* tp_members */
151
+	0,                                               /* tp_getset */
152
+	0,                                               /* tp_base */
153
+	0,                                               /* tp_dict */
154
+	0,                                               /* tp_descr_get */
155
+	0,                                               /* tp_descr_set */
156
+	0,                                               /* tp_dictoffset */
157
+	pyfcgi_ioout_init,          /* tp_init */
158
+	0,                                               /* tp_alloc */
159
+	0,                            /* tp_new */
160
+};
161
+
162
+
163
+
164
+int pyfcgi_io_init(PyObject *self)
93
 {
165
 {
94
-	IoIn *ioin = (void*)self;
95
-	ioin->in_stream = NULL;
166
+	PyIO_t *ioin = (void*)self;
167
+	ioin->io_stream = NULL;
96
 	ioin->buff = NULL;
168
 	ioin->buff = NULL;
97
 	ioin->buff_sz = 0;
169
 	ioin->buff_sz = 0;
98
 	ioin->eof=0;
170
 	ioin->eof=0;
99
 	ioin->bin=1;
171
 	ioin->bin=1;
172
+	ioin->write = NULL;
173
+	return 0;
174
+}
175
+
176
+int pyfcgi_ioin_init(PyObject *self, PyObject *args, PyObject *kwds)
177
+{
178
+	pyfcgi_io_init(self);
100
 	return 0;
179
 	return 0;
101
 }
180
 }
102
 
181
 
103
-void pyfcgi_ioin_del(IoIn *self)
182
+int pyfcgi_ioout_init(PyObject *self, PyObject *args, PyObject *kwds)
104
 {
183
 {
105
-	IoIn *ioin = self;
184
+	pyfcgi_io_init(self);
185
+	return 0;
186
+}
187
+
188
+void pyfcgi_io_del(PyIO_t *self)
189
+{
190
+	PyIO_t *ioin = self;
106
 	if(ioin->buff) { free(ioin->buff); }
191
 	if(ioin->buff) { free(ioin->buff); }
107
 	Py_TYPE(self)->tp_free((PyObject*)self);
192
 	Py_TYPE(self)->tp_free((PyObject*)self);
108
 }
193
 }
109
 
194
 
110
-PyObject* pyfcgi_ioin_close(PyObject *self, PyObject **argv, Py_ssize_t argc)
195
+PyObject* pyfcgi_io_close(PyObject *self, PyObject **argv, Py_ssize_t argc)
111
 {
196
 {
112
 	if(_check_nullin(self)) { Py_RETURN_NONE; }
197
 	if(_check_nullin(self)) { Py_RETURN_NONE; }
113
 	if(argc)
198
 	if(argc)
117
 			argc);
202
 			argc);
118
 		Py_RETURN_NONE;
203
 		Py_RETURN_NONE;
119
 	}
204
 	}
120
-	if(FCGX_FClose(*((IoIn*)self)->in_stream) < 0)
205
+	if(FCGX_FClose(*((PyIO_t*)self)->io_stream) < 0)
121
 	{
206
 	{
122
 		PyErr_Format(PyExc_OSError,
207
 		PyErr_Format(PyExc_OSError,
123
 			"%A unable to close", self);
208
 			"%A unable to close", self);
124
 	}
209
 	}
125
-	((IoIn*)self)->closed = Py_True;
210
+	((PyIO_t*)self)->closed = Py_True;
126
 	Py_RETURN_NONE;
211
 	Py_RETURN_NONE;
127
 }
212
 }
128
 
213
 
129
-PyObject* pyfcgi_ioin_fileno(PyObject *self, PyObject **argv, Py_ssize_t argc)
214
+PyObject* pyfcgi_io_fileno(PyObject *self, PyObject **argv, Py_ssize_t argc)
130
 {
215
 {
131
 	PyErr_SetString(PyExc_OSError, "libpyfcgi.IoIn has no fileno");
216
 	PyErr_SetString(PyExc_OSError, "libpyfcgi.IoIn has no fileno");
132
 	Py_RETURN_NONE;
217
 	Py_RETURN_NONE;
133
 }
218
 }
134
 
219
 
135
-PyObject* pyfcgi_ioin_flush(PyObject *self, PyObject **argv, Py_ssize_t argc)
220
+PyObject* pyfcgi_io_flush(PyObject *self, PyObject **argv, Py_ssize_t argc)
136
 {
221
 {
137
 	if(_check_nullin(self)) { Py_RETURN_NONE; }
222
 	if(_check_nullin(self)) { Py_RETURN_NONE; }
138
 	if(argc)
223
 	if(argc)
142
 			argc);
227
 			argc);
143
 		Py_RETURN_NONE;
228
 		Py_RETURN_NONE;
144
 	}
229
 	}
145
-	if(FCGX_FFlush(*((IoIn*)self)->in_stream) < 0)
230
+	if(FCGX_FFlush(*((PyIO_t*)self)->io_stream) < 0)
146
 	{
231
 	{
147
 		PyErr_Format(PyExc_OSError,
232
 		PyErr_Format(PyExc_OSError,
148
 			"%A unable to flush", self);
233
 			"%A unable to flush", self);
150
 	Py_RETURN_NONE;
235
 	Py_RETURN_NONE;
151
 }
236
 }
152
 
237
 
153
-PyObject* pyfcgi_ioin_isatty(PyObject *self, PyObject **argv, Py_ssize_t argc)
154
-{
155
-	return Py_False;
156
-}
157
-
158
-PyObject* pyfcgi_ioin_readable(PyObject *self, PyObject **argv, Py_ssize_t argc)
159
-{
160
-	return Py_True;
161
-}
162
-
163
 PyObject* pyfcgi_ioin_readline(PyObject *self, PyObject **argv, Py_ssize_t argc)
238
 PyObject* pyfcgi_ioin_readline(PyObject *self, PyObject **argv, Py_ssize_t argc)
164
 {
239
 {
165
 	int read_n;
240
 	int read_n;
176
 	}
251
 	}
177
 	if(!argc || !argv[0])
252
 	if(!argc || !argv[0])
178
 	{
253
 	{
179
-		read_n = pyfcgi_ioin__reqbuf(self, 0);
254
+		read_n = pyfcgi_io__reqbuf(self, 0);
180
 	}
255
 	}
181
 	else
256
 	else
182
 	{
257
 	{
185
 		{
260
 		{
186
 			Py_RETURN_NONE;
261
 			Py_RETURN_NONE;
187
 		}
262
 		}
188
-		read_n = pyfcgi_ioin__reqbuf(self, (arg>INT_MAX)?INT_MAX:arg);
263
+		read_n = pyfcgi_io__reqbuf(self, (arg>INT_MAX)?INT_MAX:arg);
189
 	}
264
 	}
190
 
265
 
191
-	ret = ((IoIn*)self)->buff;
192
-	if(!FCGX_GetLine(ret, read_n, *((IoIn*)self)->in_stream))
266
+	ret = ((PyIO_t*)self)->buff;
267
+	if(!FCGX_GetLine(ret, read_n, *((PyIO_t*)self)->io_stream))
193
 	{
268
 	{
194
-		((IoIn*)self)->eof = 1;
269
+		((PyIO_t*)self)->eof = 1;
195
 		ret = "";
270
 		ret = "";
196
 	}
271
 	}
197
 //dprintf(2, "readline : '%s'\n", ret);
272
 //dprintf(2, "readline : '%s'\n", ret);
236
 	}
311
 	}
237
 	Py_INCREF(res);
312
 	Py_INCREF(res);
238
 
313
 
239
-	read_n = pyfcgi_ioin__reqbuf(self, 0);
240
-	buff = ((IoIn*)self)->buff;
314
+	read_n = pyfcgi_io__reqbuf(self, 0);
315
+	buff = ((PyIO_t*)self)->buff;
241
 	cur_str = NULL;
316
 	cur_str = NULL;
242
 
317
 
243
 	while((hint && left) || !hint)
318
 	while((hint && left) || !hint)
244
 	{
319
 	{
245
 		toread = (hint&&((size_t)read_n > left))?(int)left:read_n;
320
 		toread = (hint&&((size_t)read_n > left))?(int)left:read_n;
246
 		if(!FCGX_GetLine(buff, toread,
321
 		if(!FCGX_GetLine(buff, toread,
247
-			*((IoIn*)self)->in_stream))
322
+			*((PyIO_t*)self)->io_stream))
248
 		{
323
 		{
249
-			((IoIn*)self)->eof = 1;
324
+			((PyIO_t*)self)->eof = 1;
250
 			break;
325
 			break;
251
 		}
326
 		}
252
 		sz = strlen(buff);
327
 		sz = strlen(buff);
311
 		Py_RETURN_NONE;
386
 		Py_RETURN_NONE;
312
 	}
387
 	}
313
 
388
 
314
-	if(((IoIn*)self)->eof)
389
+	if(((PyIO_t*)self)->eof)
315
 	{
390
 	{
316
 		return IoIn__FromString(self, "");
391
 		return IoIn__FromString(self, "");
317
 	}
392
 	}
330
 		}
405
 		}
331
 	}
406
 	}
332
 	left = max;
407
 	left = max;
333
-	read_n = pyfcgi_ioin__reqbuf(self, 0);
334
-	buff = ((IoIn*)self)->buff;
408
+	read_n = pyfcgi_io__reqbuf(self, 0);
409
+	buff = ((PyIO_t*)self)->buff;
335
 	if(!(res = IoIn__FromString(self, "")))
410
 	if(!(res = IoIn__FromString(self, "")))
336
 	{
411
 	{
337
 		Py_RETURN_NONE;
412
 		Py_RETURN_NONE;
340
 	while((max && left) || !max)
415
 	while((max && left) || !max)
341
 	{
416
 	{
342
 		toread = (max&&((size_t)read_n > left))?(int)left:read_n;
417
 		toread = (max&&((size_t)read_n > left))?(int)left:read_n;
343
-		sz = FCGX_GetStr(buff, toread, *((IoIn*)self)->in_stream);
418
+		sz = FCGX_GetStr(buff, toread, *((PyIO_t*)self)->io_stream);
344
 		if(sz)
419
 		if(sz)
345
 		{
420
 		{
346
 			if(sz == toread) { buff[sz] = '\0'; }
421
 			if(sz == toread) { buff[sz] = '\0'; }
359
 
434
 
360
 		if( sz < toread)
435
 		if( sz < toread)
361
 		{
436
 		{
362
-			((IoIn*)self)->eof = 1;
437
+			((PyIO_t*)self)->eof = 1;
363
 			break;
438
 			break;
364
 		}
439
 		}
365
 	}
440
 	}
408
 	left = max = PyByteArray_Size(b);
483
 	left = max = PyByteArray_Size(b);
409
 	buff = PyByteArray_AsString(b);
484
 	buff = PyByteArray_AsString(b);
410
 	buff_ptr = buff;
485
 	buff_ptr = buff;
411
-	read_n = pyfcgi_ioin__reqbuf(self, 0);
486
+	read_n = pyfcgi_io__reqbuf(self, 0);
412
 	while(left)
487
 	while(left)
413
 	{
488
 	{
414
 		toread = left>read_n?read_n:left;
489
 		toread = left>read_n?read_n:left;
415
 		if((ret = FCGX_GetStr(buff_ptr, toread,
490
 		if((ret = FCGX_GetStr(buff_ptr, toread,
416
-			*((IoIn*)self)->in_stream)) < toread)
491
+			*((PyIO_t*)self)->io_stream)) < toread)
417
 		{
492
 		{
418
-			((IoIn*)self)->eof = 1;
493
+			((PyIO_t*)self)->eof = 1;
419
 			break;
494
 			break;
420
 		}
495
 		}
421
 		buff_ptr += ret;
496
 		buff_ptr += ret;
427
 	return b;
502
 	return b;
428
 }	
503
 }	
429
 
504
 
430
-
431
-PyObject* pyfcgi_ioin_truncate(PyObject *self, PyObject **argv, Py_ssize_t argc)
505
+PyObject* pyfcgi_ioout_writelines(PyObject *self, PyObject **argv, Py_ssize_t argc)
432
 {
506
 {
433
-	PyErr_SetString(PyExc_OSError, "libpyfcgi.IoIn cannot be truncated");
507
+	PyObject *lines, *iter, *line;
508
+	const char *bytes;
509
+	Py_ssize_t bytes_len, lineno;
510
+	if( ! *((PyIO_t*)self)->write)
511
+	{
512
+		PyErr_Format(PyExc_RuntimeError, "%A write function not set",
513
+			self);
514
+		Py_RETURN_NONE;
515
+	}
516
+	if(argc != 1)
517
+	{
518
+		PyErr_Format(PyExc_ValueError,
519
+			"libpyfcgi.IoOut.writelines() expected 1 argument but %zd given",
520
+			argc);
521
+		Py_RETURN_NONE;
522
+	}
523
+	lines = argv[0];
524
+	iter = PyObject_GetIter(lines);
525
+	if(!iter)
526
+	{
527
+		// should drop exception raised by GetIter ??
528
+		PyErr_Format(PyExc_ValueError,
529
+			"libpyfcgi.IoOut.writelines() first argument does not support iterator protocol : %A",
530
+			lines);
531
+		Py_RETURN_NONE;
532
+	}
533
+	lineno = 0;
534
+	Py_INCREF(iter);
535
+	while( (line = PyIter_Next(lines)) )
536
+	{
537
+		lineno++;
538
+		Py_INCREF(line);
539
+		if(PyUnicode_Check(line))
540
+		{
541
+			bytes = PyUnicode_AsUTF8AndSize(line, &bytes_len);
542
+			if(!bytes) { Py_RETURN_NONE; } //forward error
543
+		}
544
+		else if(PyBytes_Check(line))
545
+		{
546
+			if(PyBytes_AsStringAndSize(line, (char**)&bytes, &bytes_len) == -1)
547
+			{
548
+				Py_RETURN_NONE; //forward error
549
+			}
550
+		}
551
+		else
552
+		{
553
+			PyErr_Format(PyExc_TypeError,
554
+				"libpyfcgi.IoOut.writelines() expected argument to be\
555
+str or bytes but %A given on line %zd",
556
+				line, lineno);
557
+			Py_RETURN_NONE;
558
+		}
559
+		if( ((PyIO_t*)self)->write(bytes, bytes_len) == -1)
560
+		{
561
+			PyErr_Format(PyExc_EOFError,
562
+				"libpyfcgi.IoOut.writelines() EOF error when writing line %zd",
563
+				lineno);
564
+			Py_RETURN_NONE;
565
+		}
566
+		Py_DECREF(line);
567
+	}
568
+	Py_DECREF(iter);
434
 	Py_RETURN_NONE;
569
 	Py_RETURN_NONE;
435
 }
570
 }
436
 
571
 
437
-PyObject* pyfcgi_ioin_SeekError(PyObject *self, PyObject **argv, Py_ssize_t argc)
572
+PyObject* pyfcgi_ioout_write(PyObject *self, PyObject **argv, Py_ssize_t argc)
438
 {
573
 {
439
-	PyErr_SetString(PyExc_OSError, "libpyfcgi.IoIn is not seekable");
574
+	PyObject *b;
575
+	const char *bytes;
576
+	Py_ssize_t bytes_len;
577
+	if( ! *((PyIO_t*)self)->write)
578
+	{
579
+		PyErr_Format(PyExc_RuntimeError, "%A write function not set",
580
+			self);
581
+		Py_RETURN_NONE;
582
+	}
583
+	if(argc != 1)
584
+	{
585
+		PyErr_Format(PyExc_ValueError,
586
+			"libpyfcgi.IoOut.writelines() expected 1 argument but %zd given",
587
+			argc);
588
+		Py_RETURN_NONE;
589
+	}
590
+	b = argv[0];
591
+	if(PyBytes_Check(b))
592
+	{
593
+		if(PyBytes_AsStringAndSize(b, (char**)&bytes, &bytes_len) == -1)
594
+		{
595
+			Py_RETURN_NONE; //forward error
596
+		}
597
+	}
598
+	else if(PyUnicode_Check(b))
599
+	{
600
+		bytes = PyUnicode_AsUTF8AndSize(b, &bytes_len);
601
+		if(!bytes) { Py_RETURN_NONE; } //forward error
602
+	}
603
+	else
604
+	{
605
+		PyErr_Format(PyExc_TypeError,
606
+			"libpyfcgi.IoOut.write() expected argument to be bytes\
607
+or str but %A given on line %zd",
608
+			b);
609
+		Py_RETURN_NONE;
610
+	}
611
+	if( ((PyIO_t*)self)->write(bytes, bytes_len) == -1)
612
+	{
613
+		PyErr_Format(PyExc_EOFError,
614
+			"libpyfcgi.IoOut.writelines() EOF error when calling write");
615
+		Py_RETURN_NONE;
616
+	}
440
 	Py_RETURN_NONE;
617
 	Py_RETURN_NONE;
441
 }
618
 }
442
 
619
 
443
-PyObject* pyfcgi_ioin_WriteError(PyObject *self, PyObject **argv, Py_ssize_t argc)
620
+PyObject* pyfcgi_io_false(PyObject *self, PyObject **argv, Py_ssize_t argc)
444
 {
621
 {
445
-	PyErr_SetString(PyExc_OSError, "libpyfcgi.IoIn is not writable");
622
+	return Py_False;
623
+}
624
+
625
+PyObject* pyfcgi_io_true(PyObject *self, PyObject **argv, Py_ssize_t argc)
626
+{
627
+	return Py_True;
628
+}
629
+
630
+PyObject* pyfcgi_io_truncate(PyObject *self, PyObject **argv, Py_ssize_t argc)
631
+{
632
+	PyErr_SetString(PyExc_OSError, "libpyfcgi.Io cannot be truncated");
446
 	Py_RETURN_NONE;
633
 	Py_RETURN_NONE;
447
 }
634
 }
448
 
635
 
449
-PyObject* pyfcgi_ioin_seekable(PyObject *self, PyObject **argv, Py_ssize_t argc)
636
+PyObject* pyfcgi_io_SeekError(PyObject *self, PyObject **argv, Py_ssize_t argc)
450
 {
637
 {
451
-	return Py_False;
638
+	PyErr_SetString(PyExc_OSError, "libpyfcgi.Io is not seekable");
639
+	Py_RETURN_NONE;
452
 }
640
 }
453
 
641
 
454
-PyObject* pyfcgi_ioin_writable(PyObject *self, PyObject **argv, Py_ssize_t argc)
642
+PyObject* pyfcgi_io_WriteError(PyObject *self, PyObject **argv, Py_ssize_t argc)
455
 {
643
 {
456
-	return Py_False;
644
+	PyErr_SetString(PyExc_OSError, "libpyfcgi.IoIn is not writable");
645
+	Py_RETURN_NONE;
457
 }
646
 }
458
 
647
 
648
+PyObject* pyfcgi_io_ReadError(PyObject *self, PyObject **argv, Py_ssize_t argc)
649
+{
650
+	PyErr_SetString(PyExc_OSError, "libpyfcgi.IoOut is not readable");
651
+	Py_RETURN_NONE;
652
+}
459
 
653
 
460
 static int _check_nullin(PyObject *self)
654
 static int _check_nullin(PyObject *self)
461
 {
655
 {
462
-	if(!((IoIn*)self)->in_stream)
656
+	if(!((PyIO_t*)self)->io_stream)
463
 	{
657
 	{
464
 		PyErr_SetString(PyExc_RuntimeError,
658
 		PyErr_SetString(PyExc_RuntimeError,
465
 			"pyfcgi.IoIn called in wrong context : FGCI input not set");
659
 			"pyfcgi.IoIn called in wrong context : FGCI input not set");
466
 		return -1;
660
 		return -1;
467
 	}
661
 	}
468
-	else if(!(*(((IoIn*)self)->in_stream)))
662
+	else if(!(*(((PyIO_t*)self)->io_stream)))
469
 	{
663
 	{
470
 		PyErr_SetString(PyExc_RuntimeError,
664
 		PyErr_SetString(PyExc_RuntimeError,
471
 			"pyfcgi.IoIn called in wrong context : FGCI input is NULL");
665
 			"pyfcgi.IoIn called in wrong context : FGCI input is NULL");
474
 	return 0;
668
 	return 0;
475
 }
669
 }
476
 
670
 
477
-static int pyfcgi_ioin__reqbuf(PyObject *self, int nreq)
671
+static int pyfcgi_io__reqbuf(PyObject *self, int nreq)
478
 {
672
 {
479
-	IoIn *ioin;
673
+	PyIO_t *ioin;
480
 	void *tmp;
674
 	void *tmp;
481
 	int err;
675
 	int err;
482
 
676
 
483
-	ioin = (IoIn*)self;
677
+	ioin = (PyIO_t*)self;
484
 
678
 
485
 	if(ioin->buff_sz > nreq && ioin->buff)
679
 	if(ioin->buff_sz > nreq && ioin->buff)
486
 	{
680
 	{
508
  */
702
  */
509
 static PyObject* IoIn__Concat(PyObject *self, PyObject *left, PyObject *right)
703
 static PyObject* IoIn__Concat(PyObject *self, PyObject *left, PyObject *right)
510
 {
704
 {
511
-	if(((IoIn*)self)->bin)
705
+	if(((PyIO_t*)self)->bin)
512
 	{
706
 	{
513
 		PyBytes_Concat(&left, right);
707
 		PyBytes_Concat(&left, right);
514
 		Py_DECREF(right);
708
 		Py_DECREF(right);

Loading…
Cancel
Save