blob: 56ad788d3f11f43d252db8b353e8feea5adbf535 [file] [log] [blame]
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001#include "Python.h"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002#include "structmember.h" /* for offsetof() */
3#include "_iomodule.h"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00004
5typedef struct {
6 PyObject_HEAD
7 char *buf;
8 Py_ssize_t pos;
9 Py_ssize_t string_size;
10 size_t buf_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000011 PyObject *dict;
12 PyObject *weakreflist;
Antoine Pitrou972ee132010-09-06 18:48:21 +000013 Py_ssize_t exports;
Antoine Pitroucc66a732014-07-29 19:41:11 -040014 /** If `initvalue' != NULL, `buf' is a read-only pointer into the PyBytes
15 * referenced by `initvalue'. It must be copied prior to mutation, and
16 * released during finalization */
17 PyObject *initvalue;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000018} bytesio;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000019
Antoine Pitrou972ee132010-09-06 18:48:21 +000020typedef struct {
21 PyObject_HEAD
22 bytesio *source;
23} bytesiobuf;
24
25
Antoine Pitroucc66a732014-07-29 19:41:11 -040026#define CHECK_CLOSED(self, ret) \
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000027 if ((self)->buf == NULL) { \
28 PyErr_SetString(PyExc_ValueError, \
29 "I/O operation on closed file."); \
Antoine Pitroucc66a732014-07-29 19:41:11 -040030 return ret; \
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000031 }
32
Antoine Pitrou972ee132010-09-06 18:48:21 +000033#define CHECK_EXPORTS(self) \
34 if ((self)->exports > 0) { \
35 PyErr_SetString(PyExc_BufferError, \
36 "Existing exports of data: object cannot be re-sized"); \
37 return NULL; \
38 }
39
Antoine Pitroucc66a732014-07-29 19:41:11 -040040/* Ensure we have a buffer suitable for writing, in the case that an initvalue
41 * object was provided, and we're currently borrowing its buffer. `size'
42 * indicates the new buffer size allocated as part of unsharing, to avoid a
43 * redundant reallocation caused by any subsequent mutation. `truncate'
44 * indicates whether truncation should occur if `size` < self->string_size.
45 *
46 * Do nothing if the buffer wasn't shared. Returns 0 on success, or sets an
47 * exception and returns -1 on failure. Existing state is preserved on failure.
48 */
49static int
50unshare(bytesio *self, size_t preferred_size, int truncate)
51{
52 if (self->initvalue) {
53 Py_ssize_t copy_size;
54 char *new_buf;
55
Victor Stinner706768c2014-08-16 01:03:39 +020056 if((! truncate) && preferred_size < (size_t)self->string_size) {
Antoine Pitroucc66a732014-07-29 19:41:11 -040057 preferred_size = self->string_size;
58 }
59
Victor Stinner706768c2014-08-16 01:03:39 +020060 /* PyMem_Malloc() returns NULL if preferred_size is bigger
61 than PY_SSIZE_T_MAX */
Antoine Pitroucc66a732014-07-29 19:41:11 -040062 new_buf = (char *)PyMem_Malloc(preferred_size);
63 if (new_buf == NULL) {
64 PyErr_NoMemory();
65 return -1;
66 }
67
68 copy_size = self->string_size;
Victor Stinner706768c2014-08-16 01:03:39 +020069 if ((size_t)copy_size > preferred_size) {
Antoine Pitroucc66a732014-07-29 19:41:11 -040070 copy_size = preferred_size;
71 }
72
73 memcpy(new_buf, self->buf, copy_size);
74 Py_CLEAR(self->initvalue);
75 self->buf = new_buf;
76 self->buf_size = preferred_size;
77 self->string_size = (Py_ssize_t) copy_size;
78 }
79 return 0;
80}
Antoine Pitrou972ee132010-09-06 18:48:21 +000081
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000082/* Internal routine to get a line from the buffer of a BytesIO
83 object. Returns the length between the current position to the
84 next newline character. */
85static Py_ssize_t
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030086scan_eol(bytesio *self, Py_ssize_t len)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000087{
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030088 const char *start, *n;
89 Py_ssize_t maxlen;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000090
91 assert(self->buf != NULL);
92
93 /* Move to the end of the line, up to the end of the string, s. */
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030094 start = self->buf + self->pos;
95 maxlen = self->string_size - self->pos;
96 if (len < 0 || len > maxlen)
97 len = maxlen;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000098
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030099 if (len) {
100 n = memchr(start, '\n', len);
101 if (n)
102 /* Get the length from the current position to the end of
103 the line. */
104 len = n - start + 1;
105 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000106 assert(len >= 0);
107 assert(self->pos < PY_SSIZE_T_MAX - len);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000108
109 return len;
110}
111
112/* Internal routine for changing the size of the buffer of BytesIO objects.
113 The caller should ensure that the 'size' argument is non-negative. Returns
114 0 on success, -1 otherwise. */
115static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000116resize_buffer(bytesio *self, size_t size)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000117{
118 /* Here, unsigned types are used to avoid dealing with signed integer
119 overflow, which is undefined in C. */
120 size_t alloc = self->buf_size;
121 char *new_buf = NULL;
122
123 assert(self->buf != NULL);
124
125 /* For simplicity, stay in the range of the signed type. Anyway, Python
126 doesn't allow strings to be longer than this. */
127 if (size > PY_SSIZE_T_MAX)
128 goto overflow;
129
130 if (size < alloc / 2) {
131 /* Major downsize; resize down to exact size. */
132 alloc = size + 1;
133 }
134 else if (size < alloc) {
135 /* Within allocated size; quick exit */
136 return 0;
137 }
138 else if (size <= alloc * 1.125) {
139 /* Moderate upsize; overallocate similar to list_resize() */
140 alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
141 }
142 else {
143 /* Major upsize; resize up to exact size */
144 alloc = size + 1;
145 }
146
147 if (alloc > ((size_t)-1) / sizeof(char))
148 goto overflow;
149 new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char));
150 if (new_buf == NULL) {
151 PyErr_NoMemory();
152 return -1;
153 }
154 self->buf_size = alloc;
155 self->buf = new_buf;
156
157 return 0;
158
159 overflow:
160 PyErr_SetString(PyExc_OverflowError,
161 "new buffer size too large");
162 return -1;
163}
164
165/* Internal routine for writing a string of bytes to the buffer of a BytesIO
Antoine Pitrou1d857452012-09-05 20:11:49 +0200166 object. Returns the number of bytes written, or -1 on error. */
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000167static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000168write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000169{
Antoine Pitroucc66a732014-07-29 19:41:11 -0400170 size_t desired;
171
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000172 assert(self->buf != NULL);
173 assert(self->pos >= 0);
174 assert(len >= 0);
175
Antoine Pitroucc66a732014-07-29 19:41:11 -0400176 desired = (size_t)self->pos + len;
177 if (unshare(self, desired, 0) < 0) {
178 return -1;
179 }
180
181 if (desired > self->buf_size) {
Alexandre Vassalotti1bfe9dc82008-05-07 01:44:31 +0000182 if (resize_buffer(self, (size_t)self->pos + len) < 0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000183 return -1;
184 }
185
186 if (self->pos > self->string_size) {
187 /* In case of overseek, pad with null bytes the buffer region between
188 the end of stream and the current position.
189
190 0 lo string_size hi
191 | |<---used--->|<----------available----------->|
192 | | <--to pad-->|<---to write---> |
193 0 buf position
194 */
195 memset(self->buf + self->string_size, '\0',
196 (self->pos - self->string_size) * sizeof(char));
197 }
198
199 /* Copy the data to the internal buffer, overwriting some of the existing
200 data if self->pos < self->string_size. */
201 memcpy(self->buf + self->pos, bytes, len);
202 self->pos += len;
203
204 /* Set the new length of the internal string if it has changed. */
205 if (self->string_size < self->pos) {
206 self->string_size = self->pos;
207 }
208
209 return len;
210}
211
Antoine Pitroucc66a732014-07-29 19:41:11 -0400212/* Release or free any existing buffer, and place the BytesIO in the closed
213 * state. */
214static void
215reset(bytesio *self)
216{
217 if (self->initvalue) {
218 Py_CLEAR(self->initvalue);
219 } else if (self->buf) {
220 PyMem_Free(self->buf);
221 }
222 self->buf = NULL;
223 self->string_size = 0;
224 self->pos = 0;
225}
226
227/* Reinitialize with a new heap-allocated buffer of size `size`. Returns 0 on
228 * success, or sets an exception and returns -1 on failure. Existing state is
229 * preserved on failure. */
230static int
231reinit_private(bytesio *self, Py_ssize_t size)
232{
233 char *tmp = (char *)PyMem_Malloc(size);
234 if (tmp == NULL) {
235 PyErr_NoMemory();
236 return -1;
237 }
238 reset(self);
239 self->buf = tmp;
240 self->buf_size = size;
241 return 0;
242}
243
244/* Internal version of BytesIO.__init__; resets the object to its initial
245 * (closed) state before repopulating it, optionally by sharing a PyBytes
246 * buffer provided by `initvalue'. Returns 0 on success, or sets an exception
247 * and returns -1 on failure. */
248static int
249reinit(bytesio *self, PyObject *initvalue)
250{
251 CHECK_CLOSED(self, -1);
252
253 if (initvalue == NULL || initvalue == Py_None) {
254 if (reinit_private(self, 0) < 0) {
255 return -1;
256 }
257 } else if (PyBytes_CheckExact(initvalue)) {
258 reset(self);
259 Py_INCREF(initvalue);
260 self->initvalue = initvalue;
261 self->buf = PyBytes_AS_STRING(initvalue);
262 self->buf_size = PyBytes_GET_SIZE(initvalue);
263 self->string_size = PyBytes_GET_SIZE(initvalue);
264 } else {
265 Py_buffer buf;
266 if (PyObject_GetBuffer(initvalue, &buf, PyBUF_CONTIG_RO) < 0) {
267 return -1;
268 }
269 if (reinit_private(self, buf.len) < 0) {
270 PyBuffer_Release(&buf);
271 return -1;
272 }
273 memcpy(self->buf, buf.buf, buf.len);
274 self->string_size = buf.len;
275 PyBuffer_Release(&buf);
276 }
277 return 0;
278}
279
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000280static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000281bytesio_get_closed(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000282{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000283 if (self->buf == NULL) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000284 Py_RETURN_TRUE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000285 }
286 else {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000287 Py_RETURN_FALSE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000288 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000289}
290
Antoine Pitrou1d857452012-09-05 20:11:49 +0200291PyDoc_STRVAR(readable_doc,
292"readable() -> bool. Returns True if the IO object can be read.");
293
294PyDoc_STRVAR(writable_doc,
295"writable() -> bool. Returns True if the IO object can be written.");
296
297PyDoc_STRVAR(seekable_doc,
298"seekable() -> bool. Returns True if the IO object can be seeked.");
299
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000300/* Generic getter for the writable, readable and seekable properties */
301static PyObject *
Antoine Pitrou1d857452012-09-05 20:11:49 +0200302return_not_closed(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000303{
Antoine Pitroucc66a732014-07-29 19:41:11 -0400304 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000305 Py_RETURN_TRUE;
306}
307
308PyDoc_STRVAR(flush_doc,
309"flush() -> None. Does nothing.");
310
311static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000312bytesio_flush(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000313{
Antoine Pitroucc66a732014-07-29 19:41:11 -0400314 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000315 Py_RETURN_NONE;
316}
317
Antoine Pitrou972ee132010-09-06 18:48:21 +0000318PyDoc_STRVAR(getbuffer_doc,
319"getbuffer() -> bytes.\n"
320"\n"
321"Get a read-write view over the contents of the BytesIO object.");
322
323static PyObject *
324bytesio_getbuffer(bytesio *self)
325{
326 PyTypeObject *type = &_PyBytesIOBuffer_Type;
327 bytesiobuf *buf;
328 PyObject *view;
329
Antoine Pitroucc66a732014-07-29 19:41:11 -0400330 CHECK_CLOSED(self, NULL);
Antoine Pitrou972ee132010-09-06 18:48:21 +0000331
332 buf = (bytesiobuf *) type->tp_alloc(type, 0);
333 if (buf == NULL)
334 return NULL;
335 Py_INCREF(self);
336 buf->source = self;
337 view = PyMemoryView_FromObject((PyObject *) buf);
338 Py_DECREF(buf);
339 return view;
340}
341
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000342PyDoc_STRVAR(getval_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000343"getvalue() -> bytes.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000344"\n"
345"Retrieve the entire contents of the BytesIO object.");
346
347static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000348bytesio_getvalue(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000349{
Antoine Pitroucc66a732014-07-29 19:41:11 -0400350 CHECK_CLOSED(self, NULL);
Christian Heimes72b710a2008-05-26 13:28:38 +0000351 return PyBytes_FromStringAndSize(self->buf, self->string_size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000352}
353
354PyDoc_STRVAR(isatty_doc,
355"isatty() -> False.\n"
356"\n"
357"Always returns False since BytesIO objects are not connected\n"
358"to a tty-like device.");
359
360static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000361bytesio_isatty(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000362{
Antoine Pitroucc66a732014-07-29 19:41:11 -0400363 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000364 Py_RETURN_FALSE;
365}
366
367PyDoc_STRVAR(tell_doc,
368"tell() -> current file position, an integer\n");
369
370static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000371bytesio_tell(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000372{
Antoine Pitroucc66a732014-07-29 19:41:11 -0400373 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000374 return PyLong_FromSsize_t(self->pos);
375}
376
377PyDoc_STRVAR(read_doc,
378"read([size]) -> read at most size bytes, returned as a string.\n"
379"\n"
380"If the size argument is negative, read until EOF is reached.\n"
381"Return an empty string at EOF.");
382
383static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000384bytesio_read(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000385{
386 Py_ssize_t size, n;
387 char *output;
388 PyObject *arg = Py_None;
389
Antoine Pitroucc66a732014-07-29 19:41:11 -0400390 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000391
392 if (!PyArg_ParseTuple(args, "|O:read", &arg))
393 return NULL;
394
395 if (PyLong_Check(arg)) {
396 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000397 if (size == -1 && PyErr_Occurred())
398 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000399 }
400 else if (arg == Py_None) {
401 /* Read until EOF is reached, by default. */
402 size = -1;
403 }
404 else {
405 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
406 Py_TYPE(arg)->tp_name);
407 return NULL;
408 }
409
410 /* adjust invalid sizes */
411 n = self->string_size - self->pos;
412 if (size < 0 || size > n) {
413 size = n;
414 if (size < 0)
415 size = 0;
416 }
417
418 assert(self->buf != NULL);
419 output = self->buf + self->pos;
420 self->pos += size;
421
Christian Heimes72b710a2008-05-26 13:28:38 +0000422 return PyBytes_FromStringAndSize(output, size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000423}
424
425
426PyDoc_STRVAR(read1_doc,
427"read1(size) -> read at most size bytes, returned as a string.\n"
428"\n"
429"If the size argument is negative or omitted, read until EOF is reached.\n"
430"Return an empty string at EOF.");
431
432static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000433bytesio_read1(bytesio *self, PyObject *n)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000434{
435 PyObject *arg, *res;
436
437 arg = PyTuple_Pack(1, n);
438 if (arg == NULL)
439 return NULL;
440 res = bytesio_read(self, arg);
441 Py_DECREF(arg);
442 return res;
443}
444
445PyDoc_STRVAR(readline_doc,
446"readline([size]) -> next line from the file, as a string.\n"
447"\n"
448"Retain newline. A non-negative size argument limits the maximum\n"
449"number of bytes to return (an incomplete line may be returned then).\n"
450"Return an empty string at EOF.\n");
451
452static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000453bytesio_readline(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000454{
455 Py_ssize_t size, n;
456 char *output;
457 PyObject *arg = Py_None;
458
Antoine Pitroucc66a732014-07-29 19:41:11 -0400459 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000460
461 if (!PyArg_ParseTuple(args, "|O:readline", &arg))
462 return NULL;
463
464 if (PyLong_Check(arg)) {
465 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000466 if (size == -1 && PyErr_Occurred())
467 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000468 }
469 else if (arg == Py_None) {
470 /* No size limit, by default. */
471 size = -1;
472 }
473 else {
474 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
475 Py_TYPE(arg)->tp_name);
476 return NULL;
477 }
478
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300479 n = scan_eol(self, size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000480
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300481 output = self->buf + self->pos;
482 self->pos += n;
Christian Heimes72b710a2008-05-26 13:28:38 +0000483 return PyBytes_FromStringAndSize(output, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000484}
485
486PyDoc_STRVAR(readlines_doc,
487"readlines([size]) -> list of strings, each a line from the file.\n"
488"\n"
489"Call readline() repeatedly and return a list of the lines so read.\n"
490"The optional size argument, if given, is an approximate bound on the\n"
491"total number of bytes in the lines returned.\n");
492
493static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000494bytesio_readlines(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000495{
496 Py_ssize_t maxsize, size, n;
497 PyObject *result, *line;
498 char *output;
499 PyObject *arg = Py_None;
500
Antoine Pitroucc66a732014-07-29 19:41:11 -0400501 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000502
503 if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
504 return NULL;
505
506 if (PyLong_Check(arg)) {
507 maxsize = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000508 if (maxsize == -1 && PyErr_Occurred())
509 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000510 }
511 else if (arg == Py_None) {
512 /* No size limit, by default. */
513 maxsize = -1;
514 }
515 else {
516 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
517 Py_TYPE(arg)->tp_name);
518 return NULL;
519 }
520
521 size = 0;
522 result = PyList_New(0);
523 if (!result)
524 return NULL;
525
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300526 output = self->buf + self->pos;
527 while ((n = scan_eol(self, -1)) != 0) {
528 self->pos += n;
Christian Heimes72b710a2008-05-26 13:28:38 +0000529 line = PyBytes_FromStringAndSize(output, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000530 if (!line)
531 goto on_error;
532 if (PyList_Append(result, line) == -1) {
533 Py_DECREF(line);
534 goto on_error;
535 }
536 Py_DECREF(line);
537 size += n;
538 if (maxsize > 0 && size >= maxsize)
539 break;
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300540 output += n;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000541 }
542 return result;
543
544 on_error:
545 Py_DECREF(result);
546 return NULL;
547}
548
549PyDoc_STRVAR(readinto_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000550"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000551"\n"
552"Returns number of bytes read (0 for EOF), or None if the object\n"
553"is set not to block as has no data to read.");
554
555static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000556bytesio_readinto(bytesio *self, PyObject *buffer)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000557{
558 void *raw_buffer;
Benjamin Petersonfa735552010-11-20 17:24:04 +0000559 Py_ssize_t len, n;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000560
Antoine Pitroucc66a732014-07-29 19:41:11 -0400561 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000562
563 if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1)
564 return NULL;
565
Benjamin Petersonfa735552010-11-20 17:24:04 +0000566 /* adjust invalid sizes */
567 n = self->string_size - self->pos;
568 if (len > n) {
569 len = n;
570 if (len < 0)
571 len = 0;
572 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000573
574 memcpy(raw_buffer, self->buf + self->pos, len);
575 assert(self->pos + len < PY_SSIZE_T_MAX);
576 assert(len >= 0);
577 self->pos += len;
578
579 return PyLong_FromSsize_t(len);
580}
581
582PyDoc_STRVAR(truncate_doc,
583"truncate([size]) -> int. Truncate the file to at most size bytes.\n"
584"\n"
585"Size defaults to the current file position, as returned by tell().\n"
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000586"The current file position is unchanged. Returns the new size.\n");
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000587
588static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000589bytesio_truncate(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000590{
591 Py_ssize_t size;
592 PyObject *arg = Py_None;
593
Antoine Pitroucc66a732014-07-29 19:41:11 -0400594 CHECK_CLOSED(self, NULL);
Antoine Pitrou972ee132010-09-06 18:48:21 +0000595 CHECK_EXPORTS(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000596
597 if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
598 return NULL;
599
600 if (PyLong_Check(arg)) {
601 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000602 if (size == -1 && PyErr_Occurred())
603 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000604 }
605 else if (arg == Py_None) {
606 /* Truncate to current position if no argument is passed. */
607 size = self->pos;
608 }
609 else {
610 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
611 Py_TYPE(arg)->tp_name);
612 return NULL;
613 }
614
615 if (size < 0) {
616 PyErr_Format(PyExc_ValueError,
617 "negative size value %zd", size);
618 return NULL;
619 }
620
Antoine Pitroucc66a732014-07-29 19:41:11 -0400621 if (unshare(self, size, 1) < 0) {
622 return NULL;
623 }
624
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000625 if (size < self->string_size) {
626 self->string_size = size;
627 if (resize_buffer(self, size) < 0)
628 return NULL;
629 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000630
631 return PyLong_FromSsize_t(size);
632}
633
634static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000635bytesio_iternext(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000636{
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300637 const char *next;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000638 Py_ssize_t n;
639
Antoine Pitroucc66a732014-07-29 19:41:11 -0400640 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000641
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300642 n = scan_eol(self, -1);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000643
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300644 if (n == 0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000645 return NULL;
646
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300647 next = self->buf + self->pos;
648 self->pos += n;
Christian Heimes72b710a2008-05-26 13:28:38 +0000649 return PyBytes_FromStringAndSize(next, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000650}
651
652PyDoc_STRVAR(seek_doc,
653"seek(pos, whence=0) -> int. Change stream position.\n"
654"\n"
655"Seek to byte offset pos relative to position indicated by whence:\n"
656" 0 Start of stream (the default). pos should be >= 0;\n"
657" 1 Current position - pos may be negative;\n"
658" 2 End of stream - pos usually negative.\n"
659"Returns the new absolute position.");
660
661static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000662bytesio_seek(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000663{
664 Py_ssize_t pos;
665 int mode = 0;
666
Antoine Pitroucc66a732014-07-29 19:41:11 -0400667 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000668
669 if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode))
670 return NULL;
671
672 if (pos < 0 && mode == 0) {
673 PyErr_Format(PyExc_ValueError,
674 "negative seek value %zd", pos);
675 return NULL;
676 }
677
678 /* mode 0: offset relative to beginning of the string.
679 mode 1: offset relative to current position.
680 mode 2: offset relative the end of the string. */
681 if (mode == 1) {
682 if (pos > PY_SSIZE_T_MAX - self->pos) {
683 PyErr_SetString(PyExc_OverflowError,
684 "new position too large");
685 return NULL;
686 }
687 pos += self->pos;
688 }
689 else if (mode == 2) {
690 if (pos > PY_SSIZE_T_MAX - self->string_size) {
691 PyErr_SetString(PyExc_OverflowError,
692 "new position too large");
693 return NULL;
694 }
695 pos += self->string_size;
696 }
697 else if (mode != 0) {
698 PyErr_Format(PyExc_ValueError,
699 "invalid whence (%i, should be 0, 1 or 2)", mode);
700 return NULL;
701 }
702
703 if (pos < 0)
704 pos = 0;
705 self->pos = pos;
706
707 return PyLong_FromSsize_t(self->pos);
708}
709
710PyDoc_STRVAR(write_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000711"write(bytes) -> int. Write bytes to file.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000712"\n"
713"Return the number of bytes written.");
714
715static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000716bytesio_write(bytesio *self, PyObject *obj)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000717{
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000718 Py_ssize_t n = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000719 Py_buffer buf;
720 PyObject *result = NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000721
Antoine Pitroucc66a732014-07-29 19:41:11 -0400722 CHECK_CLOSED(self, NULL);
Antoine Pitrou972ee132010-09-06 18:48:21 +0000723 CHECK_EXPORTS(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000724
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000725 if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000726 return NULL;
727
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000728 if (buf.len != 0)
729 n = write_bytes(self, buf.buf, buf.len);
730 if (n >= 0)
731 result = PyLong_FromSsize_t(n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000732
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000733 PyBuffer_Release(&buf);
734 return result;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000735}
736
737PyDoc_STRVAR(writelines_doc,
Alexandre Vassalotti7d060892008-05-07 01:47:37 +0000738"writelines(sequence_of_strings) -> None. Write strings to the file.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000739"\n"
Alexandre Vassalotti7d060892008-05-07 01:47:37 +0000740"Note that newlines are not added. The sequence can be any iterable\n"
741"object producing strings. This is equivalent to calling write() for\n"
742"each string.");
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000743
744static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000745bytesio_writelines(bytesio *self, PyObject *v)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000746{
747 PyObject *it, *item;
748 PyObject *ret;
749
Antoine Pitroucc66a732014-07-29 19:41:11 -0400750 CHECK_CLOSED(self, NULL);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000751
752 it = PyObject_GetIter(v);
753 if (it == NULL)
754 return NULL;
755
756 while ((item = PyIter_Next(it)) != NULL) {
757 ret = bytesio_write(self, item);
758 Py_DECREF(item);
759 if (ret == NULL) {
760 Py_DECREF(it);
761 return NULL;
762 }
763 Py_DECREF(ret);
764 }
765 Py_DECREF(it);
766
767 /* See if PyIter_Next failed */
768 if (PyErr_Occurred())
769 return NULL;
770
771 Py_RETURN_NONE;
772}
773
774PyDoc_STRVAR(close_doc,
775"close() -> None. Disable all I/O operations.");
776
777static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000778bytesio_close(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000779{
Antoine Pitroucc66a732014-07-29 19:41:11 -0400780 reset(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000781 Py_RETURN_NONE;
782}
783
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000784/* Pickling support.
785
786 Note that only pickle protocol 2 and onward are supported since we use
787 extended __reduce__ API of PEP 307 to make BytesIO instances picklable.
788
789 Providing support for protocol < 2 would require the __reduce_ex__ method
790 which is notably long-winded when defined properly.
791
792 For BytesIO, the implementation would similar to one coded for
793 object.__reduce_ex__, but slightly less general. To be more specific, we
794 could call bytesio_getstate directly and avoid checking for the presence of
795 a fallback __reduce__ method. However, we would still need a __newobj__
796 function to use the efficient instance representation of PEP 307.
797 */
798
799static PyObject *
800bytesio_getstate(bytesio *self)
801{
802 PyObject *initvalue = bytesio_getvalue(self);
803 PyObject *dict;
804 PyObject *state;
805
806 if (initvalue == NULL)
807 return NULL;
808 if (self->dict == NULL) {
809 Py_INCREF(Py_None);
810 dict = Py_None;
811 }
812 else {
813 dict = PyDict_Copy(self->dict);
Stefan Krah96efdd42012-09-08 11:12:33 +0200814 if (dict == NULL) {
815 Py_DECREF(initvalue);
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000816 return NULL;
Stefan Krah96efdd42012-09-08 11:12:33 +0200817 }
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000818 }
819
820 state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
821 Py_DECREF(initvalue);
822 return state;
823}
824
825static PyObject *
826bytesio_setstate(bytesio *self, PyObject *state)
827{
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000828 PyObject *position_obj;
829 PyObject *dict;
830 Py_ssize_t pos;
831
Antoine Pitroucc66a732014-07-29 19:41:11 -0400832 CHECK_EXPORTS(self);
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000833 assert(state != NULL);
834
835 /* We allow the state tuple to be longer than 3, because we may need
836 someday to extend the object's state without breaking
837 backward-compatibility. */
838 if (!PyTuple_Check(state) || Py_SIZE(state) < 3) {
839 PyErr_Format(PyExc_TypeError,
840 "%.200s.__setstate__ argument should be 3-tuple, got %.200s",
841 Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
842 return NULL;
843 }
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000844
Antoine Pitroucc66a732014-07-29 19:41:11 -0400845 /* Reset the object to its default state and set the value of the internal
846 * buffer. If state[0] does not support the buffer protocol, reinit() will
847 * raise the appropriate TypeError. */
848 if (reinit(self, PyTuple_GET_ITEM(state, 0)) < 0) {
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000849 return NULL;
Antoine Pitroucc66a732014-07-29 19:41:11 -0400850 }
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000851
852 /* Set carefully the position value. Alternatively, we could use the seek
853 method instead of modifying self->pos directly to better protect the
854 object internal state against errneous (or malicious) inputs. */
855 position_obj = PyTuple_GET_ITEM(state, 1);
856 if (!PyLong_Check(position_obj)) {
857 PyErr_Format(PyExc_TypeError,
858 "second item of state must be an integer, not %.200s",
859 Py_TYPE(position_obj)->tp_name);
860 return NULL;
861 }
862 pos = PyLong_AsSsize_t(position_obj);
863 if (pos == -1 && PyErr_Occurred())
864 return NULL;
865 if (pos < 0) {
866 PyErr_SetString(PyExc_ValueError,
867 "position value cannot be negative");
868 return NULL;
869 }
870 self->pos = pos;
871
872 /* Set the dictionary of the instance variables. */
873 dict = PyTuple_GET_ITEM(state, 2);
874 if (dict != Py_None) {
875 if (!PyDict_Check(dict)) {
876 PyErr_Format(PyExc_TypeError,
877 "third item of state should be a dict, got a %.200s",
878 Py_TYPE(dict)->tp_name);
879 return NULL;
880 }
881 if (self->dict) {
882 /* Alternatively, we could replace the internal dictionary
883 completely. However, it seems more practical to just update it. */
884 if (PyDict_Update(self->dict, dict) < 0)
885 return NULL;
886 }
887 else {
888 Py_INCREF(dict);
889 self->dict = dict;
890 }
891 }
892
893 Py_RETURN_NONE;
894}
895
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000896static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000897bytesio_dealloc(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000898{
Alexandre Vassalottifc477042009-07-22 02:24:49 +0000899 _PyObject_GC_UNTRACK(self);
Antoine Pitrou972ee132010-09-06 18:48:21 +0000900 if (self->exports > 0) {
901 PyErr_SetString(PyExc_SystemError,
902 "deallocated BytesIO object has exported buffers");
903 PyErr_Print();
904 }
Antoine Pitroucc66a732014-07-29 19:41:11 -0400905
906 reset(self);
907
Alexandre Vassalottifc477042009-07-22 02:24:49 +0000908 Py_CLEAR(self->dict);
909 if (self->weakreflist != NULL)
910 PyObject_ClearWeakRefs((PyObject *) self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000911 Py_TYPE(self)->tp_free(self);
912}
913
914static PyObject *
915bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
916{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000917 bytesio *self;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000918
919 assert(type != NULL && type->tp_alloc != NULL);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000920 self = (bytesio *)type->tp_alloc(type, 0);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000921 if (self == NULL)
922 return NULL;
923
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000924 /* tp_alloc initializes all the fields to zero. So we don't have to
925 initialize them here. */
926
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000927 self->buf = (char *)PyMem_Malloc(0);
928 if (self->buf == NULL) {
929 Py_DECREF(self);
930 return PyErr_NoMemory();
931 }
932
933 return (PyObject *)self;
934}
935
936static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000937bytesio_init(bytesio *self, PyObject *args, PyObject *kwds)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000938{
Alexandre Vassalottiba5c7432009-08-04 23:19:13 +0000939 char *kwlist[] = {"initial_bytes", NULL};
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000940 PyObject *initvalue = NULL;
941
Alexandre Vassalottiba5c7432009-08-04 23:19:13 +0000942 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:BytesIO", kwlist,
943 &initvalue))
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000944 return -1;
945
Antoine Pitroucc66a732014-07-29 19:41:11 -0400946 return reinit(self, initvalue);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000947}
948
Antoine Pitrou8f328d02012-07-30 00:01:06 +0200949static PyObject *
950bytesio_sizeof(bytesio *self, void *unused)
951{
952 Py_ssize_t res;
953
954 res = sizeof(bytesio);
955 if (self->buf)
956 res += self->buf_size;
957 return PyLong_FromSsize_t(res);
958}
959
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000960static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000961bytesio_traverse(bytesio *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000962{
963 Py_VISIT(self->dict);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000964 return 0;
965}
966
967static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000968bytesio_clear(bytesio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000969{
970 Py_CLEAR(self->dict);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000971 return 0;
972}
973
974
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000975static PyGetSetDef bytesio_getsetlist[] = {
976 {"closed", (getter)bytesio_get_closed, NULL,
977 "True if the file is closed."},
Benjamin Peterson1fea3212009-04-19 03:15:20 +0000978 {NULL}, /* sentinel */
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000979};
980
981static struct PyMethodDef bytesio_methods[] = {
Antoine Pitrou1d857452012-09-05 20:11:49 +0200982 {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc},
983 {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc},
984 {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc},
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000985 {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
986 {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
987 {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
988 {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc},
989 {"write", (PyCFunction)bytesio_write, METH_O, write_doc},
990 {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc},
991 {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc},
992 {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc},
993 {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc},
994 {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc},
995 {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc},
Antoine Pitrou972ee132010-09-06 18:48:21 +0000996 {"getbuffer", (PyCFunction)bytesio_getbuffer, METH_NOARGS, getbuffer_doc},
Antoine Pitroud5c3f6c2010-09-02 19:48:07 +0000997 {"getvalue", (PyCFunction)bytesio_getvalue, METH_NOARGS, getval_doc},
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000998 {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc},
999 {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc},
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +00001000 {"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL},
1001 {"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL},
Antoine Pitrou8f328d02012-07-30 00:01:06 +02001002 {"__sizeof__", (PyCFunction)bytesio_sizeof, METH_NOARGS, NULL},
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001003 {NULL, NULL} /* sentinel */
1004};
1005
1006PyDoc_STRVAR(bytesio_doc,
1007"BytesIO([buffer]) -> object\n"
1008"\n"
1009"Create a buffered I/O implementation using an in-memory bytes\n"
1010"buffer, ready for reading and writing.");
1011
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001012PyTypeObject PyBytesIO_Type = {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001013 PyVarObject_HEAD_INIT(NULL, 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001014 "_io.BytesIO", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001015 sizeof(bytesio), /*tp_basicsize*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001016 0, /*tp_itemsize*/
1017 (destructor)bytesio_dealloc, /*tp_dealloc*/
1018 0, /*tp_print*/
1019 0, /*tp_getattr*/
1020 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +00001021 0, /*tp_reserved*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001022 0, /*tp_repr*/
1023 0, /*tp_as_number*/
1024 0, /*tp_as_sequence*/
1025 0, /*tp_as_mapping*/
1026 0, /*tp_hash*/
1027 0, /*tp_call*/
1028 0, /*tp_str*/
1029 0, /*tp_getattro*/
1030 0, /*tp_setattro*/
1031 0, /*tp_as_buffer*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001032 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1033 Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001034 bytesio_doc, /*tp_doc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035 (traverseproc)bytesio_traverse, /*tp_traverse*/
1036 (inquiry)bytesio_clear, /*tp_clear*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001037 0, /*tp_richcompare*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001038 offsetof(bytesio, weakreflist), /*tp_weaklistoffset*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001039 PyObject_SelfIter, /*tp_iter*/
1040 (iternextfunc)bytesio_iternext, /*tp_iternext*/
1041 bytesio_methods, /*tp_methods*/
1042 0, /*tp_members*/
1043 bytesio_getsetlist, /*tp_getset*/
1044 0, /*tp_base*/
1045 0, /*tp_dict*/
1046 0, /*tp_descr_get*/
1047 0, /*tp_descr_set*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001048 offsetof(bytesio, dict), /*tp_dictoffset*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001049 (initproc)bytesio_init, /*tp_init*/
1050 0, /*tp_alloc*/
1051 bytesio_new, /*tp_new*/
1052};
Antoine Pitrou972ee132010-09-06 18:48:21 +00001053
1054
1055/*
1056 * Implementation of the small intermediate object used by getbuffer().
1057 * getbuffer() returns a memoryview over this object, which should make it
1058 * invisible from Python code.
1059 */
1060
1061static int
1062bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
1063{
1064 int ret;
Antoine Pitrou972ee132010-09-06 18:48:21 +00001065 bytesio *b = (bytesio *) obj->source;
1066 if (view == NULL) {
1067 b->exports++;
1068 return 0;
1069 }
Antoine Pitrou972ee132010-09-06 18:48:21 +00001070 ret = PyBuffer_FillInfo(view, (PyObject*)obj, b->buf, b->string_size,
1071 0, flags);
1072 if (ret >= 0) {
1073 b->exports++;
1074 }
1075 return ret;
1076}
1077
1078static void
1079bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view)
1080{
1081 bytesio *b = (bytesio *) obj->source;
1082 b->exports--;
1083}
1084
1085static int
1086bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg)
1087{
1088 Py_VISIT(self->source);
1089 return 0;
1090}
1091
1092static void
1093bytesiobuf_dealloc(bytesiobuf *self)
1094{
1095 Py_CLEAR(self->source);
1096 Py_TYPE(self)->tp_free(self);
1097}
1098
1099static PyBufferProcs bytesiobuf_as_buffer = {
1100 (getbufferproc) bytesiobuf_getbuffer,
1101 (releasebufferproc) bytesiobuf_releasebuffer,
1102};
1103
1104PyTypeObject _PyBytesIOBuffer_Type = {
1105 PyVarObject_HEAD_INIT(NULL, 0)
1106 "_io._BytesIOBuffer", /*tp_name*/
1107 sizeof(bytesiobuf), /*tp_basicsize*/
1108 0, /*tp_itemsize*/
1109 (destructor)bytesiobuf_dealloc, /*tp_dealloc*/
1110 0, /*tp_print*/
1111 0, /*tp_getattr*/
1112 0, /*tp_setattr*/
1113 0, /*tp_reserved*/
1114 0, /*tp_repr*/
1115 0, /*tp_as_number*/
1116 0, /*tp_as_sequence*/
1117 0, /*tp_as_mapping*/
1118 0, /*tp_hash*/
1119 0, /*tp_call*/
1120 0, /*tp_str*/
1121 0, /*tp_getattro*/
1122 0, /*tp_setattro*/
1123 &bytesiobuf_as_buffer, /*tp_as_buffer*/
1124 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1125 0, /*tp_doc*/
1126 (traverseproc)bytesiobuf_traverse, /*tp_traverse*/
1127 0, /*tp_clear*/
1128 0, /*tp_richcompare*/
1129 0, /*tp_weaklistoffset*/
1130 0, /*tp_iter*/
1131 0, /*tp_iternext*/
1132 0, /*tp_methods*/
1133 0, /*tp_members*/
1134 0, /*tp_getset*/
1135 0, /*tp_base*/
1136 0, /*tp_dict*/
1137 0, /*tp_descr_get*/
1138 0, /*tp_descr_set*/
1139 0, /*tp_dictoffset*/
1140 0, /*tp_init*/
1141 0, /*tp_alloc*/
1142 0, /*tp_new*/
1143};