blob: daef78fe7052e15993d1a9bc1df67d4de1bf8203 [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;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000013} bytesio;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000014
15#define CHECK_CLOSED(self) \
16 if ((self)->buf == NULL) { \
17 PyErr_SetString(PyExc_ValueError, \
18 "I/O operation on closed file."); \
19 return NULL; \
20 }
21
22/* Internal routine to get a line from the buffer of a BytesIO
23 object. Returns the length between the current position to the
24 next newline character. */
25static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000026get_line(bytesio *self, char **output)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000027{
28 char *n;
29 const char *str_end;
30 Py_ssize_t len;
31
32 assert(self->buf != NULL);
33
34 /* Move to the end of the line, up to the end of the string, s. */
35 str_end = self->buf + self->string_size;
36 for (n = self->buf + self->pos;
37 n < str_end && *n != '\n';
38 n++);
39
40 /* Skip the newline character */
41 if (n < str_end)
42 n++;
43
44 /* Get the length from the current position to the end of the line. */
45 len = n - (self->buf + self->pos);
46 *output = self->buf + self->pos;
47
48 assert(len >= 0);
49 assert(self->pos < PY_SSIZE_T_MAX - len);
50 self->pos += len;
51
52 return len;
53}
54
55/* Internal routine for changing the size of the buffer of BytesIO objects.
56 The caller should ensure that the 'size' argument is non-negative. Returns
57 0 on success, -1 otherwise. */
58static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000059resize_buffer(bytesio *self, size_t size)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000060{
61 /* Here, unsigned types are used to avoid dealing with signed integer
62 overflow, which is undefined in C. */
63 size_t alloc = self->buf_size;
64 char *new_buf = NULL;
65
66 assert(self->buf != NULL);
67
68 /* For simplicity, stay in the range of the signed type. Anyway, Python
69 doesn't allow strings to be longer than this. */
70 if (size > PY_SSIZE_T_MAX)
71 goto overflow;
72
73 if (size < alloc / 2) {
74 /* Major downsize; resize down to exact size. */
75 alloc = size + 1;
76 }
77 else if (size < alloc) {
78 /* Within allocated size; quick exit */
79 return 0;
80 }
81 else if (size <= alloc * 1.125) {
82 /* Moderate upsize; overallocate similar to list_resize() */
83 alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
84 }
85 else {
86 /* Major upsize; resize up to exact size */
87 alloc = size + 1;
88 }
89
90 if (alloc > ((size_t)-1) / sizeof(char))
91 goto overflow;
92 new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char));
93 if (new_buf == NULL) {
94 PyErr_NoMemory();
95 return -1;
96 }
97 self->buf_size = alloc;
98 self->buf = new_buf;
99
100 return 0;
101
102 overflow:
103 PyErr_SetString(PyExc_OverflowError,
104 "new buffer size too large");
105 return -1;
106}
107
108/* Internal routine for writing a string of bytes to the buffer of a BytesIO
109 object. Returns the number of bytes wrote, or -1 on error. */
110static Py_ssize_t
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000111write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000112{
113 assert(self->buf != NULL);
114 assert(self->pos >= 0);
115 assert(len >= 0);
116
Alexandre Vassalotti1bfe9dc82008-05-07 01:44:31 +0000117 if ((size_t)self->pos + len > self->buf_size) {
118 if (resize_buffer(self, (size_t)self->pos + len) < 0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000119 return -1;
120 }
121
122 if (self->pos > self->string_size) {
123 /* In case of overseek, pad with null bytes the buffer region between
124 the end of stream and the current position.
125
126 0 lo string_size hi
127 | |<---used--->|<----------available----------->|
128 | | <--to pad-->|<---to write---> |
129 0 buf position
130 */
131 memset(self->buf + self->string_size, '\0',
132 (self->pos - self->string_size) * sizeof(char));
133 }
134
135 /* Copy the data to the internal buffer, overwriting some of the existing
136 data if self->pos < self->string_size. */
137 memcpy(self->buf + self->pos, bytes, len);
138 self->pos += len;
139
140 /* Set the new length of the internal string if it has changed. */
141 if (self->string_size < self->pos) {
142 self->string_size = self->pos;
143 }
144
145 return len;
146}
147
148static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000149bytesio_get_closed(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000150{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000151 if (self->buf == NULL) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000152 Py_RETURN_TRUE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000153 }
154 else {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000155 Py_RETURN_FALSE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000156 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000157}
158
159/* Generic getter for the writable, readable and seekable properties */
160static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000161return_true(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000162{
163 Py_RETURN_TRUE;
164}
165
166PyDoc_STRVAR(flush_doc,
167"flush() -> None. Does nothing.");
168
169static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000170bytesio_flush(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000171{
172 Py_RETURN_NONE;
173}
174
175PyDoc_STRVAR(getval_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000176"getvalue() -> bytes.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000177"\n"
178"Retrieve the entire contents of the BytesIO object.");
179
180static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000181bytesio_getvalue(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000182{
183 CHECK_CLOSED(self);
Christian Heimes72b710a2008-05-26 13:28:38 +0000184 return PyBytes_FromStringAndSize(self->buf, self->string_size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000185}
186
187PyDoc_STRVAR(isatty_doc,
188"isatty() -> False.\n"
189"\n"
190"Always returns False since BytesIO objects are not connected\n"
191"to a tty-like device.");
192
193static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000194bytesio_isatty(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000195{
196 CHECK_CLOSED(self);
197 Py_RETURN_FALSE;
198}
199
200PyDoc_STRVAR(tell_doc,
201"tell() -> current file position, an integer\n");
202
203static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000204bytesio_tell(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000205{
206 CHECK_CLOSED(self);
207 return PyLong_FromSsize_t(self->pos);
208}
209
210PyDoc_STRVAR(read_doc,
211"read([size]) -> read at most size bytes, returned as a string.\n"
212"\n"
213"If the size argument is negative, read until EOF is reached.\n"
214"Return an empty string at EOF.");
215
216static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000217bytesio_read(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000218{
219 Py_ssize_t size, n;
220 char *output;
221 PyObject *arg = Py_None;
222
223 CHECK_CLOSED(self);
224
225 if (!PyArg_ParseTuple(args, "|O:read", &arg))
226 return NULL;
227
228 if (PyLong_Check(arg)) {
229 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000230 if (size == -1 && PyErr_Occurred())
231 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000232 }
233 else if (arg == Py_None) {
234 /* Read until EOF is reached, by default. */
235 size = -1;
236 }
237 else {
238 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
239 Py_TYPE(arg)->tp_name);
240 return NULL;
241 }
242
243 /* adjust invalid sizes */
244 n = self->string_size - self->pos;
245 if (size < 0 || size > n) {
246 size = n;
247 if (size < 0)
248 size = 0;
249 }
250
251 assert(self->buf != NULL);
252 output = self->buf + self->pos;
253 self->pos += size;
254
Christian Heimes72b710a2008-05-26 13:28:38 +0000255 return PyBytes_FromStringAndSize(output, size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000256}
257
258
259PyDoc_STRVAR(read1_doc,
260"read1(size) -> read at most size bytes, returned as a string.\n"
261"\n"
262"If the size argument is negative or omitted, read until EOF is reached.\n"
263"Return an empty string at EOF.");
264
265static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000266bytesio_read1(bytesio *self, PyObject *n)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000267{
268 PyObject *arg, *res;
269
270 arg = PyTuple_Pack(1, n);
271 if (arg == NULL)
272 return NULL;
273 res = bytesio_read(self, arg);
274 Py_DECREF(arg);
275 return res;
276}
277
278PyDoc_STRVAR(readline_doc,
279"readline([size]) -> next line from the file, as a string.\n"
280"\n"
281"Retain newline. A non-negative size argument limits the maximum\n"
282"number of bytes to return (an incomplete line may be returned then).\n"
283"Return an empty string at EOF.\n");
284
285static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000286bytesio_readline(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000287{
288 Py_ssize_t size, n;
289 char *output;
290 PyObject *arg = Py_None;
291
292 CHECK_CLOSED(self);
293
294 if (!PyArg_ParseTuple(args, "|O:readline", &arg))
295 return NULL;
296
297 if (PyLong_Check(arg)) {
298 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000299 if (size == -1 && PyErr_Occurred())
300 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000301 }
302 else if (arg == Py_None) {
303 /* No size limit, by default. */
304 size = -1;
305 }
306 else {
307 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
308 Py_TYPE(arg)->tp_name);
309 return NULL;
310 }
311
312 n = get_line(self, &output);
313
314 if (size >= 0 && size < n) {
315 size = n - size;
316 n -= size;
317 self->pos -= size;
318 }
319
Christian Heimes72b710a2008-05-26 13:28:38 +0000320 return PyBytes_FromStringAndSize(output, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000321}
322
323PyDoc_STRVAR(readlines_doc,
324"readlines([size]) -> list of strings, each a line from the file.\n"
325"\n"
326"Call readline() repeatedly and return a list of the lines so read.\n"
327"The optional size argument, if given, is an approximate bound on the\n"
328"total number of bytes in the lines returned.\n");
329
330static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000331bytesio_readlines(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000332{
333 Py_ssize_t maxsize, size, n;
334 PyObject *result, *line;
335 char *output;
336 PyObject *arg = Py_None;
337
338 CHECK_CLOSED(self);
339
340 if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
341 return NULL;
342
343 if (PyLong_Check(arg)) {
344 maxsize = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000345 if (maxsize == -1 && PyErr_Occurred())
346 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000347 }
348 else if (arg == Py_None) {
349 /* No size limit, by default. */
350 maxsize = -1;
351 }
352 else {
353 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
354 Py_TYPE(arg)->tp_name);
355 return NULL;
356 }
357
358 size = 0;
359 result = PyList_New(0);
360 if (!result)
361 return NULL;
362
363 while ((n = get_line(self, &output)) != 0) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000364 line = PyBytes_FromStringAndSize(output, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000365 if (!line)
366 goto on_error;
367 if (PyList_Append(result, line) == -1) {
368 Py_DECREF(line);
369 goto on_error;
370 }
371 Py_DECREF(line);
372 size += n;
373 if (maxsize > 0 && size >= maxsize)
374 break;
375 }
376 return result;
377
378 on_error:
379 Py_DECREF(result);
380 return NULL;
381}
382
383PyDoc_STRVAR(readinto_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000384"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000385"\n"
386"Returns number of bytes read (0 for EOF), or None if the object\n"
387"is set not to block as has no data to read.");
388
389static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000390bytesio_readinto(bytesio *self, PyObject *buffer)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000391{
392 void *raw_buffer;
393 Py_ssize_t len;
394
395 CHECK_CLOSED(self);
396
397 if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1)
398 return NULL;
399
400 if (self->pos + len > self->string_size)
401 len = self->string_size - self->pos;
402
403 memcpy(raw_buffer, self->buf + self->pos, len);
404 assert(self->pos + len < PY_SSIZE_T_MAX);
405 assert(len >= 0);
406 self->pos += len;
407
408 return PyLong_FromSsize_t(len);
409}
410
411PyDoc_STRVAR(truncate_doc,
412"truncate([size]) -> int. Truncate the file to at most size bytes.\n"
413"\n"
414"Size defaults to the current file position, as returned by tell().\n"
415"Returns the new size. Imply an absolute seek to the position size.");
416
417static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000418bytesio_truncate(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000419{
420 Py_ssize_t size;
421 PyObject *arg = Py_None;
422
423 CHECK_CLOSED(self);
424
425 if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
426 return NULL;
427
428 if (PyLong_Check(arg)) {
429 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000430 if (size == -1 && PyErr_Occurred())
431 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000432 }
433 else if (arg == Py_None) {
434 /* Truncate to current position if no argument is passed. */
435 size = self->pos;
436 }
437 else {
438 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
439 Py_TYPE(arg)->tp_name);
440 return NULL;
441 }
442
443 if (size < 0) {
444 PyErr_Format(PyExc_ValueError,
445 "negative size value %zd", size);
446 return NULL;
447 }
448
449 if (size < self->string_size) {
450 self->string_size = size;
451 if (resize_buffer(self, size) < 0)
452 return NULL;
453 }
454 self->pos = size;
455
456 return PyLong_FromSsize_t(size);
457}
458
459static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000460bytesio_iternext(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000461{
462 char *next;
463 Py_ssize_t n;
464
465 CHECK_CLOSED(self);
466
467 n = get_line(self, &next);
468
469 if (!next || n == 0)
470 return NULL;
471
Christian Heimes72b710a2008-05-26 13:28:38 +0000472 return PyBytes_FromStringAndSize(next, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000473}
474
475PyDoc_STRVAR(seek_doc,
476"seek(pos, whence=0) -> int. Change stream position.\n"
477"\n"
478"Seek to byte offset pos relative to position indicated by whence:\n"
479" 0 Start of stream (the default). pos should be >= 0;\n"
480" 1 Current position - pos may be negative;\n"
481" 2 End of stream - pos usually negative.\n"
482"Returns the new absolute position.");
483
484static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000485bytesio_seek(bytesio *self, PyObject *args)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000486{
487 Py_ssize_t pos;
488 int mode = 0;
489
490 CHECK_CLOSED(self);
491
492 if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode))
493 return NULL;
494
495 if (pos < 0 && mode == 0) {
496 PyErr_Format(PyExc_ValueError,
497 "negative seek value %zd", pos);
498 return NULL;
499 }
500
501 /* mode 0: offset relative to beginning of the string.
502 mode 1: offset relative to current position.
503 mode 2: offset relative the end of the string. */
504 if (mode == 1) {
505 if (pos > PY_SSIZE_T_MAX - self->pos) {
506 PyErr_SetString(PyExc_OverflowError,
507 "new position too large");
508 return NULL;
509 }
510 pos += self->pos;
511 }
512 else if (mode == 2) {
513 if (pos > PY_SSIZE_T_MAX - self->string_size) {
514 PyErr_SetString(PyExc_OverflowError,
515 "new position too large");
516 return NULL;
517 }
518 pos += self->string_size;
519 }
520 else if (mode != 0) {
521 PyErr_Format(PyExc_ValueError,
522 "invalid whence (%i, should be 0, 1 or 2)", mode);
523 return NULL;
524 }
525
526 if (pos < 0)
527 pos = 0;
528 self->pos = pos;
529
530 return PyLong_FromSsize_t(self->pos);
531}
532
533PyDoc_STRVAR(write_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000534"write(bytes) -> int. Write bytes to file.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000535"\n"
536"Return the number of bytes written.");
537
538static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000539bytesio_write(bytesio *self, PyObject *obj)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000540{
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000541 Py_ssize_t n = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000542 Py_buffer buf;
543 PyObject *result = NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000544
545 CHECK_CLOSED(self);
546
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000547 if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000548 return NULL;
549
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000550 if (buf.len != 0)
551 n = write_bytes(self, buf.buf, buf.len);
552 if (n >= 0)
553 result = PyLong_FromSsize_t(n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000554
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000555 PyBuffer_Release(&buf);
556 return result;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000557}
558
559PyDoc_STRVAR(writelines_doc,
Alexandre Vassalotti7d060892008-05-07 01:47:37 +0000560"writelines(sequence_of_strings) -> None. Write strings to the file.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000561"\n"
Alexandre Vassalotti7d060892008-05-07 01:47:37 +0000562"Note that newlines are not added. The sequence can be any iterable\n"
563"object producing strings. This is equivalent to calling write() for\n"
564"each string.");
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000565
566static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000567bytesio_writelines(bytesio *self, PyObject *v)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000568{
569 PyObject *it, *item;
570 PyObject *ret;
571
572 CHECK_CLOSED(self);
573
574 it = PyObject_GetIter(v);
575 if (it == NULL)
576 return NULL;
577
578 while ((item = PyIter_Next(it)) != NULL) {
579 ret = bytesio_write(self, item);
580 Py_DECREF(item);
581 if (ret == NULL) {
582 Py_DECREF(it);
583 return NULL;
584 }
585 Py_DECREF(ret);
586 }
587 Py_DECREF(it);
588
589 /* See if PyIter_Next failed */
590 if (PyErr_Occurred())
591 return NULL;
592
593 Py_RETURN_NONE;
594}
595
596PyDoc_STRVAR(close_doc,
597"close() -> None. Disable all I/O operations.");
598
599static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000600bytesio_close(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000601{
602 if (self->buf != NULL) {
603 PyMem_Free(self->buf);
604 self->buf = NULL;
605 }
606 Py_RETURN_NONE;
607}
608
609static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000610bytesio_dealloc(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000611{
Alexandre Vassalottifc477042009-07-22 02:24:49 +0000612 _PyObject_GC_UNTRACK(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000613 if (self->buf != NULL) {
614 PyMem_Free(self->buf);
615 self->buf = NULL;
616 }
Alexandre Vassalottifc477042009-07-22 02:24:49 +0000617 Py_CLEAR(self->dict);
618 if (self->weakreflist != NULL)
619 PyObject_ClearWeakRefs((PyObject *) self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000620 Py_TYPE(self)->tp_free(self);
621}
622
623static PyObject *
624bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
625{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000626 bytesio *self;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000627
628 assert(type != NULL && type->tp_alloc != NULL);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000629 self = (bytesio *)type->tp_alloc(type, 0);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000630 if (self == NULL)
631 return NULL;
632
633 self->string_size = 0;
634 self->pos = 0;
635 self->buf_size = 0;
636 self->buf = (char *)PyMem_Malloc(0);
637 if (self->buf == NULL) {
638 Py_DECREF(self);
639 return PyErr_NoMemory();
640 }
641
642 return (PyObject *)self;
643}
644
645static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000646bytesio_init(bytesio *self, PyObject *args, PyObject *kwds)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000647{
648 PyObject *initvalue = NULL;
649
650 if (!PyArg_ParseTuple(args, "|O:BytesIO", &initvalue))
651 return -1;
652
653 /* In case, __init__ is called multiple times. */
654 self->string_size = 0;
655 self->pos = 0;
656
657 if (initvalue && initvalue != Py_None) {
658 PyObject *res;
659 res = bytesio_write(self, initvalue);
660 if (res == NULL)
661 return -1;
662 Py_DECREF(res);
663 self->pos = 0;
664 }
665
666 return 0;
667}
668
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000669static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000670bytesio_traverse(bytesio *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000671{
672 Py_VISIT(self->dict);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000673 return 0;
674}
675
676static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000677bytesio_clear(bytesio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000678{
679 Py_CLEAR(self->dict);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000680 return 0;
681}
682
683
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000684static PyGetSetDef bytesio_getsetlist[] = {
685 {"closed", (getter)bytesio_get_closed, NULL,
686 "True if the file is closed."},
Benjamin Peterson1fea3212009-04-19 03:15:20 +0000687 {NULL}, /* sentinel */
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000688};
689
690static struct PyMethodDef bytesio_methods[] = {
691 {"readable", (PyCFunction)return_true, METH_NOARGS, NULL},
692 {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL},
693 {"writable", (PyCFunction)return_true, METH_NOARGS, NULL},
694 {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
695 {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
696 {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
697 {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc},
698 {"write", (PyCFunction)bytesio_write, METH_O, write_doc},
699 {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc},
700 {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc},
701 {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc},
702 {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc},
703 {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc},
704 {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc},
705 {"getvalue", (PyCFunction)bytesio_getvalue, METH_VARARGS, getval_doc},
706 {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc},
707 {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc},
708 {NULL, NULL} /* sentinel */
709};
710
711PyDoc_STRVAR(bytesio_doc,
712"BytesIO([buffer]) -> object\n"
713"\n"
714"Create a buffered I/O implementation using an in-memory bytes\n"
715"buffer, ready for reading and writing.");
716
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000717PyTypeObject PyBytesIO_Type = {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000718 PyVarObject_HEAD_INIT(NULL, 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000719 "_io.BytesIO", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000720 sizeof(bytesio), /*tp_basicsize*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000721 0, /*tp_itemsize*/
722 (destructor)bytesio_dealloc, /*tp_dealloc*/
723 0, /*tp_print*/
724 0, /*tp_getattr*/
725 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000726 0, /*tp_reserved*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000727 0, /*tp_repr*/
728 0, /*tp_as_number*/
729 0, /*tp_as_sequence*/
730 0, /*tp_as_mapping*/
731 0, /*tp_hash*/
732 0, /*tp_call*/
733 0, /*tp_str*/
734 0, /*tp_getattro*/
735 0, /*tp_setattro*/
736 0, /*tp_as_buffer*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000737 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
738 Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000739 bytesio_doc, /*tp_doc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000740 (traverseproc)bytesio_traverse, /*tp_traverse*/
741 (inquiry)bytesio_clear, /*tp_clear*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000742 0, /*tp_richcompare*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000743 offsetof(bytesio, weakreflist), /*tp_weaklistoffset*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000744 PyObject_SelfIter, /*tp_iter*/
745 (iternextfunc)bytesio_iternext, /*tp_iternext*/
746 bytesio_methods, /*tp_methods*/
747 0, /*tp_members*/
748 bytesio_getsetlist, /*tp_getset*/
749 0, /*tp_base*/
750 0, /*tp_dict*/
751 0, /*tp_descr_get*/
752 0, /*tp_descr_set*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000753 offsetof(bytesio, dict), /*tp_dictoffset*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000754 (initproc)bytesio_init, /*tp_init*/
755 0, /*tp_alloc*/
756 bytesio_new, /*tp_new*/
757};