~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Modules/_bufferedio.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
 
3
    
 
4
    Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
 
5
    BufferedRandom.
 
6
    
 
7
    Written by Amaury Forgeot d'Arc and Antoine Pitrou
 
8
*/
 
9
 
 
10
#define PY_SSIZE_T_CLEAN
 
11
#include "Python.h"
 
12
#include "structmember.h"
 
13
#include "pythread.h"
 
14
#include "_iomodule.h"
 
15
 
 
16
/*
 
17
 * BufferedIOBase class, inherits from IOBase.
 
18
 */
 
19
PyDoc_STRVAR(BufferedIOBase_doc,
 
20
    "Base class for buffered IO objects.\n"
 
21
    "\n"
 
22
    "The main difference with RawIOBase is that the read() method\n"
 
23
    "supports omitting the size argument, and does not have a default\n"
 
24
    "implementation that defers to readinto().\n"
 
25
    "\n"
 
26
    "In addition, read(), readinto() and write() may raise\n"
 
27
    "BlockingIOError if the underlying raw stream is in non-blocking\n"
 
28
    "mode and not ready; unlike their raw counterparts, they will never\n"
 
29
    "return None.\n"
 
30
    "\n"
 
31
    "A typical implementation should not inherit from a RawIOBase\n"
 
32
    "implementation, but wrap one.\n"
 
33
    );
 
34
 
 
35
static PyObject *
 
36
BufferedIOBase_readinto(PyObject *self, PyObject *args)
 
37
{
 
38
    Py_buffer buf;
 
39
    Py_ssize_t len;
 
40
    PyObject *data;
 
41
 
 
42
    if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
 
43
        return NULL;
 
44
    }
 
45
 
 
46
    data = PyObject_CallMethod(self, "read", "n", buf.len);
 
47
    if (data == NULL)
 
48
        goto error;
 
49
 
 
50
    if (!PyBytes_Check(data)) {
 
51
        Py_DECREF(data);
 
52
        PyErr_SetString(PyExc_TypeError, "read() should return bytes");
 
53
        goto error;
 
54
    }
 
55
 
 
56
    len = Py_SIZE(data);
 
57
    memcpy(buf.buf, PyBytes_AS_STRING(data), len);
 
58
 
 
59
    PyBuffer_Release(&buf);
 
60
    Py_DECREF(data);
 
61
 
 
62
    return PyLong_FromSsize_t(len);
 
63
 
 
64
  error:
 
65
    PyBuffer_Release(&buf);
 
66
    return NULL;
 
67
}
 
68
 
 
69
static PyObject *
 
70
BufferedIOBase_unsupported(const char *message)
 
71
{
 
72
    PyErr_SetString(IO_STATE->unsupported_operation, message);
 
73
    return NULL;
 
74
}
 
75
 
 
76
PyDoc_STRVAR(BufferedIOBase_read_doc,
 
77
    "Read and return up to n bytes.\n"
 
78
    "\n"
 
79
    "If the argument is omitted, None, or negative, reads and\n"
 
80
    "returns all data until EOF.\n"
 
81
    "\n"
 
82
    "If the argument is positive, and the underlying raw stream is\n"
 
83
    "not 'interactive', multiple raw reads may be issued to satisfy\n"
 
84
    "the byte count (unless EOF is reached first).  But for\n"
 
85
    "interactive raw streams (as well as sockets and pipes), at most\n"
 
86
    "one raw read will be issued, and a short result does not imply\n"
 
87
    "that EOF is imminent.\n"
 
88
    "\n"
 
89
    "Returns an empty bytes object on EOF.\n"
 
90
    "\n"
 
91
    "Returns None if the underlying raw stream was open in non-blocking\n"
 
92
    "mode and no data is available at the moment.\n");
 
93
 
 
94
static PyObject *
 
95
BufferedIOBase_read(PyObject *self, PyObject *args)
 
96
{
 
97
    return BufferedIOBase_unsupported("read");
 
98
}
 
99
 
 
100
PyDoc_STRVAR(BufferedIOBase_read1_doc,
 
101
    "Read and return up to n bytes, with at most one read() call\n"
 
102
    "to the underlying raw stream. A short result does not imply\n"
 
103
    "that EOF is imminent.\n"
 
104
    "\n"
 
105
    "Returns an empty bytes object on EOF.\n");
 
106
 
 
107
static PyObject *
 
108
BufferedIOBase_read1(PyObject *self, PyObject *args)
 
109
{
 
110
    return BufferedIOBase_unsupported("read1");
 
111
}
 
112
 
 
113
PyDoc_STRVAR(BufferedIOBase_write_doc,
 
114
    "Write the given buffer to the IO stream.\n"
 
115
    "\n"
 
116
    "Returns the number of bytes written, which is never less than\n"
 
117
    "len(b).\n"
 
118
    "\n"
 
119
    "Raises BlockingIOError if the buffer is full and the\n"
 
120
    "underlying raw stream cannot accept more data at the moment.\n");
 
121
 
 
122
static PyObject *
 
123
BufferedIOBase_write(PyObject *self, PyObject *args)
 
124
{
 
125
    return BufferedIOBase_unsupported("write");
 
126
}
 
127
 
 
128
 
 
129
static PyMethodDef BufferedIOBase_methods[] = {
 
130
    {"read", BufferedIOBase_read, METH_VARARGS, BufferedIOBase_read_doc},
 
131
    {"read1", BufferedIOBase_read1, METH_VARARGS, BufferedIOBase_read1_doc},
 
132
    {"readinto", BufferedIOBase_readinto, METH_VARARGS, NULL},
 
133
    {"write", BufferedIOBase_write, METH_VARARGS, BufferedIOBase_write_doc},
 
134
    {NULL, NULL}
 
135
};
 
136
 
 
137
PyTypeObject PyBufferedIOBase_Type = {
 
138
    PyVarObject_HEAD_INIT(NULL, 0)
 
139
    "_io._BufferedIOBase",      /*tp_name*/
 
140
    0,                          /*tp_basicsize*/
 
141
    0,                          /*tp_itemsize*/
 
142
    0,                          /*tp_dealloc*/
 
143
    0,                          /*tp_print*/
 
144
    0,                          /*tp_getattr*/
 
145
    0,                          /*tp_setattr*/
 
146
    0,                          /*tp_compare */
 
147
    0,                          /*tp_repr*/
 
148
    0,                          /*tp_as_number*/
 
149
    0,                          /*tp_as_sequence*/
 
150
    0,                          /*tp_as_mapping*/
 
151
    0,                          /*tp_hash */
 
152
    0,                          /*tp_call*/
 
153
    0,                          /*tp_str*/
 
154
    0,                          /*tp_getattro*/
 
155
    0,                          /*tp_setattro*/
 
156
    0,                          /*tp_as_buffer*/
 
157
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
 
158
    BufferedIOBase_doc,         /* tp_doc */
 
159
    0,                          /* tp_traverse */
 
160
    0,                          /* tp_clear */
 
161
    0,                          /* tp_richcompare */
 
162
    0,                          /* tp_weaklistoffset */
 
163
    0,                          /* tp_iter */
 
164
    0,                          /* tp_iternext */
 
165
    BufferedIOBase_methods,     /* tp_methods */
 
166
    0,                          /* tp_members */
 
167
    0,                          /* tp_getset */
 
168
    &PyIOBase_Type,             /* tp_base */
 
169
    0,                          /* tp_dict */
 
170
    0,                          /* tp_descr_get */
 
171
    0,                          /* tp_descr_set */
 
172
    0,                          /* tp_dictoffset */
 
173
    0,                          /* tp_init */
 
174
    0,                          /* tp_alloc */
 
175
    0,                          /* tp_new */
 
176
};
 
177
 
 
178
 
 
179
typedef struct {
 
180
    PyObject_HEAD
 
181
 
 
182
    PyObject *raw;
 
183
    int ok;    /* Initialized? */
 
184
    int readable;
 
185
    int writable;
 
186
 
 
187
    /* Absolute position inside the raw stream (-1 if unknown). */
 
188
    Py_off_t abs_pos;
 
189
 
 
190
    /* A static buffer of size `buffer_size` */
 
191
    char *buffer;
 
192
    /* Current logical position in the buffer. */
 
193
    Py_off_t pos;
 
194
    /* Position of the raw stream in the buffer. */
 
195
    Py_off_t raw_pos;
 
196
 
 
197
    /* Just after the last buffered byte in the buffer, or -1 if the buffer
 
198
       isn't ready for reading. */
 
199
    Py_off_t read_end;
 
200
 
 
201
    /* Just after the last byte actually written */
 
202
    Py_off_t write_pos;
 
203
    /* Just after the last byte waiting to be written, or -1 if the buffer
 
204
       isn't ready for writing. */
 
205
    Py_off_t write_end;
 
206
 
 
207
    PyThread_type_lock lock;
 
208
 
 
209
    Py_ssize_t buffer_size;
 
210
    Py_ssize_t buffer_mask;
 
211
 
 
212
    PyObject *dict;
 
213
    PyObject *weakreflist;
 
214
} BufferedObject;
 
215
 
 
216
/*
 
217
    Implementation notes:
 
218
    
 
219
    * BufferedReader, BufferedWriter and BufferedRandom try to share most
 
220
      methods (this is helped by the members `readable` and `writable`, which
 
221
      are initialized in the respective constructors)
 
222
    * They also share a single buffer for reading and writing. This enables
 
223
      interleaved reads and writes without flushing. It also makes the logic
 
224
      a bit trickier to get right.
 
225
    * The absolute position of the raw stream is cached, if possible, in the
 
226
      `abs_pos` member. It must be updated every time an operation is done
 
227
      on the raw stream. If not sure, it can be reinitialized by calling
 
228
      _Buffered_raw_tell(), which queries the raw stream (_Buffered_raw_seek()
 
229
      also does it). To read it, use RAW_TELL().
 
230
    * Three helpers, _BufferedReader_raw_read, _BufferedWriter_raw_write and
 
231
      _BufferedWriter_flush_unlocked do a lot of useful housekeeping.
 
232
 
 
233
    NOTE: we should try to maintain block alignment of reads and writes to the
 
234
    raw stream (according to the buffer size), but for now it is only done
 
235
    in read() and friends.
 
236
    
 
237
    XXX: method naming is a bit messy.
 
238
*/
 
239
 
 
240
/* These macros protect the BufferedObject against concurrent operations. */
 
241
 
 
242
#define ENTER_BUFFERED(self) \
 
243
    Py_BEGIN_ALLOW_THREADS \
 
244
    PyThread_acquire_lock(self->lock, 1); \
 
245
    Py_END_ALLOW_THREADS
 
246
 
 
247
#define LEAVE_BUFFERED(self) \
 
248
    PyThread_release_lock(self->lock);
 
249
 
 
250
#define CHECK_INITIALIZED(self) \
 
251
    if (self->ok <= 0) { \
 
252
        PyErr_SetString(PyExc_ValueError, \
 
253
            "I/O operation on uninitialized object"); \
 
254
        return NULL; \
 
255
    }
 
256
 
 
257
#define CHECK_INITIALIZED_INT(self) \
 
258
    if (self->ok <= 0) { \
 
259
        PyErr_SetString(PyExc_ValueError, \
 
260
            "I/O operation on uninitialized object"); \
 
261
        return -1; \
 
262
    }
 
263
 
 
264
#define VALID_READ_BUFFER(self) \
 
265
    (self->readable && self->read_end != -1)
 
266
 
 
267
#define VALID_WRITE_BUFFER(self) \
 
268
    (self->writable && self->write_end != -1)
 
269
 
 
270
#define ADJUST_POSITION(self, _new_pos) \
 
271
    do { \
 
272
        self->pos = _new_pos; \
 
273
        if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
 
274
            self->read_end = self->pos; \
 
275
    } while(0)
 
276
 
 
277
#define READAHEAD(self) \
 
278
    ((self->readable && VALID_READ_BUFFER(self)) \
 
279
        ? (self->read_end - self->pos) : 0)
 
280
 
 
281
#define RAW_OFFSET(self) \
 
282
    (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
 
283
        && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
 
284
 
 
285
#define RAW_TELL(self) \
 
286
    (self->abs_pos != -1 ? self->abs_pos : _Buffered_raw_tell(self))
 
287
 
 
288
#define MINUS_LAST_BLOCK(self, size) \
 
289
    (self->buffer_mask ? \
 
290
        (size & ~self->buffer_mask) : \
 
291
        (self->buffer_size * (size / self->buffer_size)))
 
292
 
 
293
 
 
294
static void
 
295
BufferedObject_dealloc(BufferedObject *self)
 
296
{
 
297
    if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
 
298
        return;
 
299
    _PyObject_GC_UNTRACK(self);
 
300
    self->ok = 0;
 
301
    if (self->weakreflist != NULL)
 
302
        PyObject_ClearWeakRefs((PyObject *)self);
 
303
    Py_CLEAR(self->raw);
 
304
    if (self->buffer) {
 
305
        PyMem_Free(self->buffer);
 
306
        self->buffer = NULL;
 
307
    }
 
308
    if (self->lock) {
 
309
        PyThread_free_lock(self->lock);
 
310
        self->lock = NULL;
 
311
    }
 
312
    Py_CLEAR(self->dict);
 
313
    Py_TYPE(self)->tp_free((PyObject *)self);
 
314
}
 
315
 
 
316
static int
 
317
Buffered_traverse(BufferedObject *self, visitproc visit, void *arg)
 
318
{
 
319
    Py_VISIT(self->raw);
 
320
    Py_VISIT(self->dict);
 
321
    return 0;
 
322
}
 
323
 
 
324
static int
 
325
Buffered_clear(BufferedObject *self)
 
326
{
 
327
    if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
 
328
        return -1;
 
329
    self->ok = 0;
 
330
    Py_CLEAR(self->raw);
 
331
    Py_CLEAR(self->dict);
 
332
    return 0;
 
333
}
 
334
 
 
335
/*
 
336
 * _BufferedIOMixin methods
 
337
 * This is not a class, just a collection of methods that will be reused
 
338
 * by BufferedReader and BufferedWriter
 
339
 */
 
340
 
 
341
/* Flush and close */
 
342
 
 
343
static PyObject *
 
344
BufferedIOMixin_flush(BufferedObject *self, PyObject *args)
 
345
{
 
346
    CHECK_INITIALIZED(self)
 
347
    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
 
348
}
 
349
 
 
350
static int
 
351
BufferedIOMixin_closed(BufferedObject *self)
 
352
{
 
353
    int closed;
 
354
    PyObject *res;
 
355
    CHECK_INITIALIZED_INT(self)
 
356
    res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
 
357
    if (res == NULL)
 
358
        return -1;
 
359
    closed = PyObject_IsTrue(res);
 
360
    Py_DECREF(res);
 
361
    return closed;
 
362
}
 
363
 
 
364
static PyObject *
 
365
BufferedIOMixin_closed_get(BufferedObject *self, void *context)
 
366
{
 
367
    CHECK_INITIALIZED(self)
 
368
    return PyObject_GetAttr(self->raw, _PyIO_str_closed);
 
369
}
 
370
 
 
371
static PyObject *
 
372
BufferedIOMixin_close(BufferedObject *self, PyObject *args)
 
373
{
 
374
    PyObject *res = NULL;
 
375
    int r;
 
376
 
 
377
    CHECK_INITIALIZED(self)
 
378
    ENTER_BUFFERED(self)
 
379
 
 
380
    r = BufferedIOMixin_closed(self);
 
381
    if (r < 0)
 
382
        goto end;
 
383
    if (r > 0) {
 
384
        res = Py_None;
 
385
        Py_INCREF(res);
 
386
        goto end;
 
387
    }
 
388
    /* flush() will most probably re-take the lock, so drop it first */
 
389
    LEAVE_BUFFERED(self)
 
390
    res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
 
391
    ENTER_BUFFERED(self)
 
392
    if (res == NULL) {
 
393
        /* If flush() fails, just give up */
 
394
        if (PyErr_ExceptionMatches(PyExc_IOError))
 
395
            PyErr_Clear();
 
396
        else
 
397
            goto end;
 
398
    }
 
399
    Py_XDECREF(res);
 
400
 
 
401
    res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
 
402
 
 
403
end:
 
404
    LEAVE_BUFFERED(self)
 
405
    return res;
 
406
}
 
407
 
 
408
/* Inquiries */
 
409
 
 
410
static PyObject *
 
411
BufferedIOMixin_seekable(BufferedObject *self, PyObject *args)
 
412
{
 
413
    CHECK_INITIALIZED(self)
 
414
    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
 
415
}
 
416
 
 
417
static PyObject *
 
418
BufferedIOMixin_readable(BufferedObject *self, PyObject *args)
 
419
{
 
420
    CHECK_INITIALIZED(self)
 
421
    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
 
422
}
 
423
 
 
424
static PyObject *
 
425
BufferedIOMixin_writable(BufferedObject *self, PyObject *args)
 
426
{
 
427
    CHECK_INITIALIZED(self)
 
428
    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
 
429
}
 
430
 
 
431
static PyObject *
 
432
BufferedIOMixin_name_get(BufferedObject *self, void *context)
 
433
{
 
434
    CHECK_INITIALIZED(self)
 
435
    return PyObject_GetAttrString(self->raw, "name");
 
436
}
 
437
 
 
438
static PyObject *
 
439
BufferedIOMixin_mode_get(BufferedObject *self, void *context)
 
440
{
 
441
    CHECK_INITIALIZED(self)
 
442
    return PyObject_GetAttrString(self->raw, "mode");
 
443
}
 
444
 
 
445
/* Lower-level APIs */
 
446
 
 
447
static PyObject *
 
448
BufferedIOMixin_fileno(BufferedObject *self, PyObject *args)
 
449
{
 
450
    CHECK_INITIALIZED(self)
 
451
    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
 
452
}
 
453
 
 
454
static PyObject *
 
455
BufferedIOMixin_isatty(BufferedObject *self, PyObject *args)
 
456
{
 
457
    CHECK_INITIALIZED(self)
 
458
    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
 
459
}
 
460
 
 
461
 
 
462
/* Forward decls */
 
463
static PyObject *
 
464
_BufferedWriter_flush_unlocked(BufferedObject *, int);
 
465
static Py_ssize_t
 
466
_BufferedReader_fill_buffer(BufferedObject *self);
 
467
static void
 
468
_BufferedReader_reset_buf(BufferedObject *self);
 
469
static void
 
470
_BufferedWriter_reset_buf(BufferedObject *self);
 
471
static PyObject *
 
472
_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t);
 
473
static PyObject *
 
474
_BufferedReader_read_unlocked(BufferedObject *self, Py_ssize_t);
 
475
 
 
476
 
 
477
/*
 
478
 * Helpers
 
479
 */
 
480
 
 
481
/* Returns the address of the `written` member if a BlockingIOError was
 
482
   raised, NULL otherwise. The error is always re-raised. */
 
483
static Py_ssize_t *
 
484
_Buffered_check_blocking_error(void)
 
485
{
 
486
    PyObject *t, *v, *tb;
 
487
    PyBlockingIOErrorObject *err;
 
488
 
 
489
    PyErr_Fetch(&t, &v, &tb);
 
490
    if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
 
491
        PyErr_Restore(t, v, tb);
 
492
        return NULL;
 
493
    }
 
494
    err = (PyBlockingIOErrorObject *) v;
 
495
    /* TODO: sanity check (err->written >= 0) */
 
496
    PyErr_Restore(t, v, tb);
 
497
    return &err->written;
 
498
}
 
499
 
 
500
static Py_off_t
 
501
_Buffered_raw_tell(BufferedObject *self)
 
502
{
 
503
    PyObject *res;
 
504
    Py_off_t n;
 
505
    res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
 
506
    if (res == NULL)
 
507
        return -1;
 
508
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
 
509
    Py_DECREF(res);
 
510
    if (n < 0) {
 
511
        if (!PyErr_Occurred())
 
512
            PyErr_Format(PyExc_IOError,
 
513
                         "Raw stream returned invalid position %zd", n);
 
514
        return -1;
 
515
    }
 
516
    self->abs_pos = n;
 
517
    return n;
 
518
}
 
519
 
 
520
static Py_off_t
 
521
_Buffered_raw_seek(BufferedObject *self, Py_off_t target, int whence)
 
522
{
 
523
    PyObject *res, *posobj, *whenceobj;
 
524
    Py_off_t n;
 
525
 
 
526
    posobj = PyLong_FromOff_t(target);
 
527
    if (posobj == NULL)
 
528
        return -1;
 
529
    whenceobj = PyLong_FromLong(whence);
 
530
    if (whenceobj == NULL) {
 
531
        Py_DECREF(posobj);
 
532
        return -1;
 
533
    }
 
534
    res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
 
535
                                     posobj, whenceobj, NULL);
 
536
    Py_DECREF(posobj);
 
537
    Py_DECREF(whenceobj);
 
538
    if (res == NULL)
 
539
        return -1;
 
540
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
 
541
    Py_DECREF(res);
 
542
    if (n < 0) {
 
543
        if (!PyErr_Occurred())
 
544
            PyErr_Format(PyExc_IOError,
 
545
                         "Raw stream returned invalid position %zd", n);
 
546
        return -1;
 
547
    }
 
548
    self->abs_pos = n;
 
549
    return n;
 
550
}
 
551
 
 
552
static int
 
553
_Buffered_init(BufferedObject *self)
 
554
{
 
555
    Py_ssize_t n;
 
556
    if (self->buffer_size <= 0) {
 
557
        PyErr_SetString(PyExc_ValueError,
 
558
            "buffer size must be strictly positive");
 
559
        return -1;
 
560
    }
 
561
    if (self->buffer)
 
562
        PyMem_Free(self->buffer);
 
563
    self->buffer = PyMem_Malloc(self->buffer_size);
 
564
    if (self->buffer == NULL) {
 
565
        PyErr_NoMemory();
 
566
        return -1;
 
567
    }
 
568
    self->lock = PyThread_allocate_lock();
 
569
    if (self->lock == NULL) {
 
570
        PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
 
571
        return -1;
 
572
    }
 
573
    /* Find out whether buffer_size is a power of 2 */
 
574
    /* XXX is this optimization useful? */
 
575
    for (n = self->buffer_size - 1; n & 1; n >>= 1)
 
576
        ;
 
577
    if (n == 0)
 
578
        self->buffer_mask = self->buffer_size - 1;
 
579
    else
 
580
        self->buffer_mask = 0;
 
581
    if (_Buffered_raw_tell(self) == -1)
 
582
        PyErr_Clear();
 
583
    return 0;
 
584
}
 
585
 
 
586
/*
 
587
 * Shared methods and wrappers
 
588
 */
 
589
 
 
590
static PyObject *
 
591
Buffered_flush(BufferedObject *self, PyObject *args)
 
592
{
 
593
    PyObject *res;
 
594
 
 
595
    CHECK_INITIALIZED(self)
 
596
    if (BufferedIOMixin_closed(self)) {
 
597
        PyErr_SetString(PyExc_ValueError, "flush of closed file");
 
598
        return NULL;
 
599
    }
 
600
 
 
601
    ENTER_BUFFERED(self)
 
602
    res = _BufferedWriter_flush_unlocked(self, 0);
 
603
    if (res != NULL && self->readable) {
 
604
        /* Rewind the raw stream so that its position corresponds to
 
605
           the current logical position. */
 
606
        Py_off_t n;
 
607
        n = _Buffered_raw_seek(self, -RAW_OFFSET(self), 1);
 
608
        if (n == -1)
 
609
            Py_CLEAR(res);
 
610
        _BufferedReader_reset_buf(self);
 
611
    }
 
612
    LEAVE_BUFFERED(self)
 
613
 
 
614
    return res;
 
615
}
 
616
 
 
617
static PyObject *
 
618
Buffered_peek(BufferedObject *self, PyObject *args)
 
619
{
 
620
    Py_ssize_t n = 0;
 
621
    PyObject *res = NULL;
 
622
 
 
623
    CHECK_INITIALIZED(self)
 
624
    if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
 
625
        return NULL;
 
626
    }
 
627
 
 
628
    ENTER_BUFFERED(self)
 
629
 
 
630
    if (self->writable) {
 
631
        res = _BufferedWriter_flush_unlocked(self, 1);
 
632
        if (res == NULL)
 
633
            goto end;
 
634
        Py_CLEAR(res);
 
635
    }
 
636
    res = _BufferedReader_peek_unlocked(self, n);
 
637
 
 
638
end:
 
639
    LEAVE_BUFFERED(self)
 
640
    return res;
 
641
}
 
642
 
 
643
static PyObject *
 
644
Buffered_read(BufferedObject *self, PyObject *args)
 
645
{
 
646
    Py_ssize_t n = -1;
 
647
    PyObject *res;
 
648
 
 
649
    CHECK_INITIALIZED(self)
 
650
    if (!PyArg_ParseTuple(args, "|n:read", &n)) {
 
651
        return NULL;
 
652
    }
 
653
    if (n < -1) {
 
654
        PyErr_SetString(PyExc_ValueError,
 
655
                        "read length must be positive or -1");
 
656
        return NULL;
 
657
    }
 
658
 
 
659
    if (BufferedIOMixin_closed(self)) {
 
660
        PyErr_SetString(PyExc_ValueError, "read of closed file");
 
661
        return NULL;
 
662
    }
 
663
 
 
664
    ENTER_BUFFERED(self)
 
665
    res = _BufferedReader_read_unlocked(self, n);
 
666
    LEAVE_BUFFERED(self)
 
667
 
 
668
    return res;
 
669
}
 
670
 
 
671
static PyObject *
 
672
Buffered_read1(BufferedObject *self, PyObject *args)
 
673
{
 
674
    Py_ssize_t n, have, r;
 
675
    PyObject *res = NULL;
 
676
 
 
677
    CHECK_INITIALIZED(self)
 
678
    if (!PyArg_ParseTuple(args, "n:read1", &n)) {
 
679
        return NULL;
 
680
    }
 
681
 
 
682
    if (n < 0) {
 
683
        PyErr_SetString(PyExc_ValueError,
 
684
                        "read length must be positive");
 
685
        return NULL;
 
686
    }
 
687
    if (n == 0)
 
688
        return PyBytes_FromStringAndSize(NULL, 0);
 
689
 
 
690
    ENTER_BUFFERED(self)
 
691
    
 
692
    if (self->writable) {
 
693
        res = _BufferedWriter_flush_unlocked(self, 1);
 
694
        if (res == NULL)
 
695
            goto end;
 
696
        Py_CLEAR(res);
 
697
    }
 
698
 
 
699
    /* Return up to n bytes.  If at least one byte is buffered, we
 
700
       only return buffered bytes.  Otherwise, we do one raw read. */
 
701
 
 
702
    /* XXX: this mimicks the io.py implementation but is probably wrong.
 
703
       If we need to read from the raw stream, then we could actually read
 
704
       all `n` bytes asked by the caller (and possibly more, so as to fill
 
705
       our buffer for the next reads). */
 
706
 
 
707
    have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
 
708
    if (have > 0) {
 
709
        if (n > have)
 
710
            n = have;
 
711
        res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
 
712
        if (res == NULL)
 
713
            goto end;
 
714
        self->pos += n;
 
715
        goto end;
 
716
    }
 
717
 
 
718
    /* Fill the buffer from the raw stream, and copy it to the result. */
 
719
    _BufferedReader_reset_buf(self);
 
720
    r = _BufferedReader_fill_buffer(self);
 
721
    if (r == -1)
 
722
        goto end;
 
723
    if (r == -2)
 
724
        r = 0;
 
725
    if (n > r)
 
726
        n = r;
 
727
    res = PyBytes_FromStringAndSize(self->buffer, n);
 
728
    if (res == NULL)
 
729
        goto end;
 
730
    self->pos = n;
 
731
 
 
732
end:
 
733
    LEAVE_BUFFERED(self)
 
734
    return res;
 
735
}
 
736
 
 
737
static PyObject *
 
738
Buffered_readinto(BufferedObject *self, PyObject *args)
 
739
{
 
740
    PyObject *res = NULL;
 
741
 
 
742
    CHECK_INITIALIZED(self)
 
743
    
 
744
    /* TODO: use raw.readinto() instead! */
 
745
    if (self->writable) {
 
746
        ENTER_BUFFERED(self)
 
747
        res = _BufferedWriter_flush_unlocked(self, 0);
 
748
        LEAVE_BUFFERED(self)
 
749
        if (res == NULL)
 
750
            goto end;
 
751
        Py_DECREF(res);
 
752
    }
 
753
    res = BufferedIOBase_readinto((PyObject *)self, args);
 
754
 
 
755
end:
 
756
    return res;
 
757
}
 
758
 
 
759
static PyObject *
 
760
_Buffered_readline(BufferedObject *self, Py_ssize_t limit)
 
761
{
 
762
    PyObject *res = NULL;
 
763
    PyObject *chunks = NULL;
 
764
    Py_ssize_t n, written = 0;
 
765
    const char *start, *s, *end;
 
766
 
 
767
    if (BufferedIOMixin_closed(self)) {
 
768
        PyErr_SetString(PyExc_ValueError, "readline of closed file");
 
769
        return NULL;
 
770
    }
 
771
 
 
772
    ENTER_BUFFERED(self)
 
773
 
 
774
    /* First, try to find a line in the buffer */
 
775
    n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
 
776
    if (limit >= 0 && n > limit)
 
777
        n = limit;
 
778
    start = self->buffer + self->pos;
 
779
    end = start + n;
 
780
    s = start;
 
781
    while (s < end) {
 
782
        if (*s++ == '\n') {
 
783
            res = PyBytes_FromStringAndSize(start, s - start);
 
784
            if (res != NULL)
 
785
                self->pos += s - start;
 
786
            goto end;
 
787
        }
 
788
    }
 
789
    if (n == limit) {
 
790
        res = PyBytes_FromStringAndSize(start, n);
 
791
        if (res != NULL)
 
792
            self->pos += n;
 
793
        goto end;
 
794
    }
 
795
 
 
796
    /* Now we try to get some more from the raw stream */
 
797
    if (self->writable) {
 
798
        res = _BufferedWriter_flush_unlocked(self, 1);
 
799
        if (res == NULL)
 
800
            goto end;
 
801
        Py_CLEAR(res);
 
802
    }
 
803
    chunks = PyList_New(0);
 
804
    if (chunks == NULL)
 
805
        goto end;
 
806
    if (n > 0) {
 
807
        res = PyBytes_FromStringAndSize(start, n);
 
808
        if (res == NULL)
 
809
            goto end;
 
810
        if (PyList_Append(chunks, res) < 0) {
 
811
            Py_CLEAR(res);
 
812
            goto end;
 
813
        }
 
814
        Py_CLEAR(res);
 
815
        written += n;
 
816
        if (limit >= 0)
 
817
            limit -= n;
 
818
    }
 
819
 
 
820
    for (;;) {
 
821
        _BufferedReader_reset_buf(self);
 
822
        n = _BufferedReader_fill_buffer(self);
 
823
        if (n == -1)
 
824
            goto end;
 
825
        if (n <= 0)
 
826
            break;
 
827
        if (limit >= 0 && n > limit)
 
828
            n = limit;
 
829
        start = self->buffer;
 
830
        end = start + n;
 
831
        s = start;
 
832
        while (s < end) {
 
833
            if (*s++ == '\n') {
 
834
                res = PyBytes_FromStringAndSize(start, s - start);
 
835
                if (res == NULL)
 
836
                    goto end;
 
837
                self->pos = s - start;
 
838
                goto found;
 
839
            }
 
840
        }
 
841
        res = PyBytes_FromStringAndSize(start, n);
 
842
        if (res == NULL)
 
843
            goto end;
 
844
        if (n == limit) {
 
845
            self->pos = n;
 
846
            break;
 
847
        }
 
848
        if (PyList_Append(chunks, res) < 0) {
 
849
            Py_CLEAR(res);
 
850
            goto end;
 
851
        }
 
852
        Py_CLEAR(res);
 
853
        written += n;
 
854
        if (limit >= 0)
 
855
            limit -= n;
 
856
    }
 
857
found:
 
858
    if (res != NULL && PyList_Append(chunks, res) < 0) {
 
859
        Py_CLEAR(res);
 
860
        goto end;
 
861
    }
 
862
    Py_CLEAR(res);
 
863
    res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
 
864
 
 
865
end:
 
866
    LEAVE_BUFFERED(self)
 
867
    Py_XDECREF(chunks);
 
868
    return res;
 
869
}
 
870
 
 
871
static PyObject *
 
872
Buffered_readline(BufferedObject *self, PyObject *args)
 
873
{
 
874
    Py_ssize_t limit = -1;
 
875
 
 
876
    CHECK_INITIALIZED(self)
 
877
 
 
878
    if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
 
879
        return NULL;
 
880
    }
 
881
    return _Buffered_readline(self, limit);
 
882
}
 
883
 
 
884
 
 
885
static PyObject *
 
886
Buffered_tell(BufferedObject *self, PyObject *args)
 
887
{
 
888
    Py_off_t pos;
 
889
 
 
890
    CHECK_INITIALIZED(self)
 
891
    pos = _Buffered_raw_tell(self);
 
892
    if (pos == -1)
 
893
        return NULL;
 
894
    pos -= RAW_OFFSET(self);
 
895
    /* TODO: sanity check (pos >= 0) */
 
896
    return PyLong_FromOff_t(pos);
 
897
}
 
898
 
 
899
static PyObject *
 
900
Buffered_seek(BufferedObject *self, PyObject *args)
 
901
{
 
902
    Py_off_t target, n;
 
903
    int whence = 0;
 
904
    PyObject *targetobj, *res = NULL;
 
905
 
 
906
    CHECK_INITIALIZED(self)
 
907
    if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
 
908
        return NULL;
 
909
    }
 
910
    
 
911
    if (whence < 0 || whence > 2) {
 
912
        PyErr_Format(PyExc_ValueError,
 
913
                     "whence must be between 0 and 2, not %d", whence);
 
914
        return NULL;
 
915
    }
 
916
    target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
 
917
    if (target == -1 && PyErr_Occurred())
 
918
        return NULL;
 
919
 
 
920
    ENTER_BUFFERED(self)
 
921
 
 
922
    if (whence != 2 && self->readable) {
 
923
        Py_off_t current, avail;
 
924
        /* Check if seeking leaves us inside the current buffer,
 
925
           so as to return quickly if possible.
 
926
           Don't know how to do that when whence == 2, though. */
 
927
        current = RAW_TELL(self);
 
928
        avail = READAHEAD(self);
 
929
        if (avail > 0) {
 
930
            Py_off_t offset;
 
931
            if (whence == 0)
 
932
                offset = target - (current - RAW_OFFSET(self));
 
933
            else
 
934
                offset = target;
 
935
            if (offset >= -self->pos && offset <= avail) {
 
936
                self->pos += offset;
 
937
                res = PyLong_FromOff_t(current - avail + offset);
 
938
                goto end;
 
939
            }
 
940
        }
 
941
    }
 
942
 
 
943
    /* Fallback: invoke raw seek() method and clear buffer */
 
944
    if (self->writable) {
 
945
        res = _BufferedWriter_flush_unlocked(self, 0);
 
946
        if (res == NULL)
 
947
            goto end;
 
948
        Py_CLEAR(res);
 
949
        _BufferedWriter_reset_buf(self);
 
950
    }
 
951
 
 
952
    /* TODO: align on block boundary and read buffer if needed? */
 
953
    if (whence == 1)
 
954
        target -= RAW_OFFSET(self);
 
955
    n = _Buffered_raw_seek(self, target, whence);
 
956
    if (n == -1)
 
957
        goto end;
 
958
    self->raw_pos = -1;
 
959
    res = PyLong_FromOff_t(n);
 
960
    if (res != NULL && self->readable)
 
961
        _BufferedReader_reset_buf(self);
 
962
 
 
963
end:
 
964
    LEAVE_BUFFERED(self)
 
965
    return res;
 
966
}
 
967
 
 
968
static PyObject *
 
969
Buffered_truncate(BufferedObject *self, PyObject *args)
 
970
{
 
971
    PyObject *pos = Py_None;
 
972
    PyObject *res = NULL;
 
973
 
 
974
    CHECK_INITIALIZED(self)
 
975
    if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
 
976
        return NULL;
 
977
    }
 
978
 
 
979
    ENTER_BUFFERED(self)
 
980
 
 
981
    if (self->writable) {
 
982
        res = _BufferedWriter_flush_unlocked(self, 0);
 
983
        if (res == NULL)
 
984
            goto end;
 
985
        Py_CLEAR(res);
 
986
    }
 
987
    if (self->readable) {
 
988
        if (pos == Py_None) {
 
989
            /* Rewind the raw stream so that its position corresponds to
 
990
               the current logical position. */
 
991
            if (_Buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
 
992
                goto end;
 
993
        }
 
994
        _BufferedReader_reset_buf(self);
 
995
    }
 
996
    res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
 
997
    if (res == NULL)
 
998
        goto end;
 
999
    /* Reset cached position */
 
1000
    if (_Buffered_raw_tell(self) == -1)
 
1001
        PyErr_Clear();
 
1002
 
 
1003
end:
 
1004
    LEAVE_BUFFERED(self)
 
1005
    return res;
 
1006
}
 
1007
 
 
1008
static PyObject *
 
1009
Buffered_iternext(BufferedObject *self)
 
1010
{
 
1011
    PyObject *line;
 
1012
    PyTypeObject *tp;
 
1013
 
 
1014
    CHECK_INITIALIZED(self);
 
1015
 
 
1016
    tp = Py_TYPE(self);
 
1017
    if (tp == &PyBufferedReader_Type ||
 
1018
        tp == &PyBufferedRandom_Type) {
 
1019
        /* Skip method call overhead for speed */
 
1020
        line = _Buffered_readline(self, -1);
 
1021
    }
 
1022
    else {
 
1023
        line = PyObject_CallMethodObjArgs((PyObject *)self,
 
1024
                                           _PyIO_str_readline, NULL);
 
1025
        if (line && !PyBytes_Check(line)) {
 
1026
            PyErr_Format(PyExc_IOError,
 
1027
                         "readline() should have returned a bytes object, "
 
1028
                         "not '%.200s'", Py_TYPE(line)->tp_name);
 
1029
            Py_DECREF(line);
 
1030
            return NULL;
 
1031
        }
 
1032
    }
 
1033
 
 
1034
    if (line == NULL)
 
1035
        return NULL;
 
1036
 
 
1037
    if (PyBytes_GET_SIZE(line) == 0) {
 
1038
        /* Reached EOF or would have blocked */
 
1039
        Py_DECREF(line);
 
1040
        return NULL;
 
1041
    }
 
1042
 
 
1043
    return line;
 
1044
}
 
1045
 
 
1046
/*
 
1047
 * class BufferedReader
 
1048
 */
 
1049
 
 
1050
PyDoc_STRVAR(BufferedReader_doc,
 
1051
             "Create a new buffered reader using the given readable raw IO object.");
 
1052
 
 
1053
static void _BufferedReader_reset_buf(BufferedObject *self)
 
1054
{
 
1055
    self->read_end = -1;
 
1056
}
 
1057
 
 
1058
static int
 
1059
BufferedReader_init(BufferedObject *self, PyObject *args, PyObject *kwds)
 
1060
{
 
1061
    char *kwlist[] = {"raw", "buffer_size", NULL};
 
1062
    Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
 
1063
    PyObject *raw;
 
1064
 
 
1065
    self->ok = 0;
 
1066
 
 
1067
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
 
1068
                                     &raw, &buffer_size)) {
 
1069
        return -1;
 
1070
    }
 
1071
 
 
1072
    if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
 
1073
        return -1;
 
1074
 
 
1075
    Py_CLEAR(self->raw);
 
1076
    Py_INCREF(raw);
 
1077
    self->raw = raw;
 
1078
    self->buffer_size = buffer_size;
 
1079
    self->readable = 1;
 
1080
    self->writable = 0;
 
1081
 
 
1082
    if (_Buffered_init(self) < 0)
 
1083
        return -1;
 
1084
    _BufferedReader_reset_buf(self);
 
1085
 
 
1086
    self->ok = 1;
 
1087
    return 0;
 
1088
}
 
1089
 
 
1090
static Py_ssize_t
 
1091
_BufferedReader_raw_read(BufferedObject *self, char *start, Py_ssize_t len)
 
1092
{
 
1093
    Py_buffer buf;
 
1094
    PyObject *memobj, *res;
 
1095
    Py_ssize_t n;
 
1096
    /* NOTE: the buffer needn't be released as its object is NULL. */
 
1097
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
 
1098
        return -1;
 
1099
    memobj = PyMemoryView_FromBuffer(&buf);
 
1100
    if (memobj == NULL)
 
1101
        return -1;
 
1102
    res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
 
1103
    Py_DECREF(memobj);
 
1104
    if (res == NULL)
 
1105
        return -1;
 
1106
    if (res == Py_None) {
 
1107
        /* Non-blocking stream would have blocked. Special return code! */
 
1108
        Py_DECREF(res);
 
1109
        return -2;
 
1110
    }
 
1111
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
 
1112
    Py_DECREF(res);
 
1113
    if (n < 0 || n > len) {
 
1114
        PyErr_Format(PyExc_IOError,
 
1115
                     "raw readinto() returned invalid length %zd "
 
1116
                     "(should have been between 0 and %zd)", n, len);
 
1117
        return -1;
 
1118
    }
 
1119
    if (n > 0 && self->abs_pos != -1)
 
1120
        self->abs_pos += n;
 
1121
    return n;
 
1122
}
 
1123
 
 
1124
static Py_ssize_t
 
1125
_BufferedReader_fill_buffer(BufferedObject *self)
 
1126
{
 
1127
    Py_ssize_t start, len, n;
 
1128
    if (VALID_READ_BUFFER(self))
 
1129
        start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
 
1130
    else
 
1131
        start = 0;
 
1132
    len = self->buffer_size - start;
 
1133
    n = _BufferedReader_raw_read(self, self->buffer + start, len);
 
1134
    if (n <= 0)
 
1135
        return n;
 
1136
    self->read_end = start + n;
 
1137
    self->raw_pos = start + n;
 
1138
    return n;
 
1139
}
 
1140
 
 
1141
static PyObject *
 
1142
_BufferedReader_read_unlocked(BufferedObject *self, Py_ssize_t n)
 
1143
{
 
1144
    PyObject *data, *res = NULL;
 
1145
    Py_ssize_t current_size, remaining, written;
 
1146
    char *out;
 
1147
    static PyObject *sep = NULL;
 
1148
 
 
1149
    /* Special case for when the number of bytes to read is unspecified. */
 
1150
    if (n == -1) {
 
1151
        PyObject *chunks = PyList_New(0);
 
1152
        if (chunks == NULL)
 
1153
            return NULL;
 
1154
 
 
1155
        /* First copy what we have in the current buffer. */
 
1156
        current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
 
1157
        data = NULL;
 
1158
        if (current_size) {
 
1159
            data = PyBytes_FromStringAndSize(
 
1160
                self->buffer + self->pos, current_size);
 
1161
            if (data == NULL) {
 
1162
                Py_DECREF(chunks);
 
1163
                return NULL;
 
1164
            }
 
1165
        }
 
1166
        _BufferedReader_reset_buf(self);
 
1167
        /* We're going past the buffer's bounds, flush it */
 
1168
        if (self->writable) {
 
1169
            res = _BufferedWriter_flush_unlocked(self, 1);
 
1170
            if (res == NULL) {
 
1171
                Py_DECREF(chunks);
 
1172
                return NULL;
 
1173
            }
 
1174
            Py_CLEAR(res);
 
1175
        }
 
1176
        while (1) {
 
1177
            if (data) {
 
1178
                if (PyList_Append(chunks, data) < 0) {
 
1179
                    Py_DECREF(data);
 
1180
                    Py_DECREF(chunks);
 
1181
                    return NULL;
 
1182
                }
 
1183
                Py_DECREF(data);
 
1184
            }
 
1185
 
 
1186
            /* Read until EOF or until read() would block. */
 
1187
            data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
 
1188
            if (data == NULL) {
 
1189
                Py_DECREF(chunks);
 
1190
                return NULL;
 
1191
            }
 
1192
            if (data != Py_None && !PyBytes_Check(data)) {
 
1193
                Py_DECREF(data);
 
1194
                Py_DECREF(chunks);
 
1195
                PyErr_SetString(PyExc_TypeError, "read() should return bytes");
 
1196
                return NULL;
 
1197
            }
 
1198
            if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
 
1199
                if (current_size == 0) {
 
1200
                    Py_DECREF(chunks);
 
1201
                    return data;
 
1202
                }
 
1203
                else {
 
1204
                    if (sep == NULL) {
 
1205
                        sep = PyBytes_FromStringAndSize(NULL, 0);
 
1206
                        if (sep == NULL) {
 
1207
                            Py_DECREF(data);
 
1208
                            Py_DECREF(chunks);
 
1209
                            return NULL;
 
1210
                        }
 
1211
                    }
 
1212
                    res =_PyBytes_Join(sep, chunks);
 
1213
                    Py_DECREF(data);
 
1214
                    Py_DECREF(chunks);
 
1215
                    return res;
 
1216
                }
 
1217
            }
 
1218
            current_size += PyBytes_GET_SIZE(data);
 
1219
            if (self->abs_pos != -1)
 
1220
                self->abs_pos += PyBytes_GET_SIZE(data);
 
1221
        }
 
1222
    }
 
1223
 
 
1224
    /* The number of bytes to read is specified, return at most n bytes. */
 
1225
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
 
1226
    if (n <= current_size) {
 
1227
        /* Fast path: the data to read is fully buffered. */
 
1228
        res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
 
1229
        if (res == NULL)
 
1230
            goto error;
 
1231
        self->pos += n;
 
1232
        return res;
 
1233
    }
 
1234
 
 
1235
    /* Slow path: read from the stream until enough bytes are read,
 
1236
     * or until an EOF occurs or until read() would block.
 
1237
     */
 
1238
    res = PyBytes_FromStringAndSize(NULL, n);
 
1239
    if (res == NULL)
 
1240
        goto error;
 
1241
    out = PyBytes_AS_STRING(res);
 
1242
    remaining = n;
 
1243
    written = 0;
 
1244
    if (current_size > 0) {
 
1245
        memcpy(out, self->buffer + self->pos, current_size);
 
1246
        remaining -= current_size;
 
1247
        written += current_size;
 
1248
    }
 
1249
    _BufferedReader_reset_buf(self);
 
1250
    while (remaining > 0) {
 
1251
        /* We want to read a whole block at the end into buffer.
 
1252
           If we had readv() we could do this in one pass. */
 
1253
        Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
 
1254
        if (r == 0)
 
1255
            break;
 
1256
        r = _BufferedReader_raw_read(self, out + written, r);
 
1257
        if (r == -1)
 
1258
            goto error;
 
1259
        if (r == 0 || r == -2) {
 
1260
            /* EOF occurred or read() would block. */
 
1261
            if (r == 0 || written > 0) {
 
1262
                if (_PyBytes_Resize(&res, written))
 
1263
                    goto error;
 
1264
                return res;
 
1265
            }
 
1266
            Py_DECREF(res);
 
1267
            Py_INCREF(Py_None);
 
1268
            return Py_None;
 
1269
        }
 
1270
        remaining -= r;
 
1271
        written += r;
 
1272
    }
 
1273
    assert(remaining <= self->buffer_size);
 
1274
    self->pos = 0;
 
1275
    self->raw_pos = 0;
 
1276
    self->read_end = 0;
 
1277
    while (self->read_end < self->buffer_size) {
 
1278
        Py_ssize_t r = _BufferedReader_fill_buffer(self);
 
1279
        if (r == -1)
 
1280
            goto error;
 
1281
        if (r == 0 || r == -2) {
 
1282
            /* EOF occurred or read() would block. */
 
1283
            if (r == 0 || written > 0) {
 
1284
                if (_PyBytes_Resize(&res, written))
 
1285
                    goto error;
 
1286
                return res;
 
1287
            }
 
1288
            Py_DECREF(res);
 
1289
            Py_INCREF(Py_None);
 
1290
            return Py_None;
 
1291
        }
 
1292
        if (remaining > r) {
 
1293
            memcpy(out + written, self->buffer + self->pos, r);
 
1294
            written += r;
 
1295
            self->pos += r;
 
1296
            remaining -= r;
 
1297
        }
 
1298
        else if (remaining > 0) {
 
1299
            memcpy(out + written, self->buffer + self->pos, remaining);
 
1300
            written += remaining;
 
1301
            self->pos += remaining;
 
1302
            remaining = 0;
 
1303
        }
 
1304
        if (remaining == 0)
 
1305
            break;
 
1306
    }
 
1307
 
 
1308
    return res;
 
1309
 
 
1310
error:
 
1311
    Py_XDECREF(res);
 
1312
    return NULL;
 
1313
}
 
1314
 
 
1315
static PyObject *
 
1316
_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n)
 
1317
{
 
1318
    Py_ssize_t have, r;
 
1319
 
 
1320
    have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
 
1321
    /* Constraints:
 
1322
       1. we don't want to advance the file position.
 
1323
       2. we don't want to lose block alignment, so we can't shift the buffer
 
1324
          to make some place.
 
1325
       Therefore, we either return `have` bytes (if > 0), or a full buffer.
 
1326
    */
 
1327
    if (have > 0) {
 
1328
        return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
 
1329
    }
 
1330
 
 
1331
    /* Fill the buffer from the raw stream, and copy it to the result. */
 
1332
    _BufferedReader_reset_buf(self);
 
1333
    r = _BufferedReader_fill_buffer(self);
 
1334
    if (r == -1)
 
1335
        return NULL;
 
1336
    if (r == -2)
 
1337
        r = 0;
 
1338
    self->pos = 0;
 
1339
    return PyBytes_FromStringAndSize(self->buffer, r);
 
1340
}
 
1341
 
 
1342
static PyMethodDef BufferedReader_methods[] = {
 
1343
    /* BufferedIOMixin methods */
 
1344
    {"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS},
 
1345
    {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
 
1346
    {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
 
1347
    {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
 
1348
    {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
 
1349
    {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
 
1350
    {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
 
1351
 
 
1352
    {"read", (PyCFunction)Buffered_read, METH_VARARGS},
 
1353
    {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
 
1354
    {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
 
1355
    {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
 
1356
    {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
 
1357
    {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
 
1358
    {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
 
1359
    {NULL, NULL}
 
1360
};
 
1361
 
 
1362
static PyMemberDef BufferedReader_members[] = {
 
1363
    {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
 
1364
    {NULL}
 
1365
};
 
1366
 
 
1367
static PyGetSetDef BufferedReader_getset[] = {
 
1368
    {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
 
1369
    {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
 
1370
    {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
 
1371
    {0}
 
1372
};
 
1373
 
 
1374
 
 
1375
PyTypeObject PyBufferedReader_Type = {
 
1376
    PyVarObject_HEAD_INIT(NULL, 0)
 
1377
    "_io.BufferedReader",       /*tp_name*/
 
1378
    sizeof(BufferedObject),     /*tp_basicsize*/
 
1379
    0,                          /*tp_itemsize*/
 
1380
    (destructor)BufferedObject_dealloc,     /*tp_dealloc*/
 
1381
    0,                          /*tp_print*/
 
1382
    0,                          /*tp_getattr*/
 
1383
    0,                          /*tp_setattr*/
 
1384
    0,                          /*tp_compare */
 
1385
    0,                          /*tp_repr*/
 
1386
    0,                          /*tp_as_number*/
 
1387
    0,                          /*tp_as_sequence*/
 
1388
    0,                          /*tp_as_mapping*/
 
1389
    0,                          /*tp_hash */
 
1390
    0,                          /*tp_call*/
 
1391
    0,                          /*tp_str*/
 
1392
    0,                          /*tp_getattro*/
 
1393
    0,                          /*tp_setattro*/
 
1394
    0,                          /*tp_as_buffer*/
 
1395
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
 
1396
            | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
 
1397
    BufferedReader_doc,         /* tp_doc */
 
1398
    (traverseproc)Buffered_traverse, /* tp_traverse */
 
1399
    (inquiry)Buffered_clear,    /* tp_clear */
 
1400
    0,                          /* tp_richcompare */
 
1401
    offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
 
1402
    0,                          /* tp_iter */
 
1403
    (iternextfunc)Buffered_iternext, /* tp_iternext */
 
1404
    BufferedReader_methods,     /* tp_methods */
 
1405
    BufferedReader_members,     /* tp_members */
 
1406
    BufferedReader_getset,      /* tp_getset */
 
1407
    0,                          /* tp_base */
 
1408
    0,                          /* tp_dict */
 
1409
    0,                          /* tp_descr_get */
 
1410
    0,                          /* tp_descr_set */
 
1411
    offsetof(BufferedObject, dict), /* tp_dictoffset */
 
1412
    (initproc)BufferedReader_init, /* tp_init */
 
1413
    0,                          /* tp_alloc */
 
1414
    PyType_GenericNew,          /* tp_new */
 
1415
};
 
1416
 
 
1417
 
 
1418
/*
 
1419
 * class BufferedWriter
 
1420
 */
 
1421
PyDoc_STRVAR(BufferedWriter_doc,
 
1422
    "A buffer for a writeable sequential RawIO object.\n"
 
1423
    "\n"
 
1424
    "The constructor creates a BufferedWriter for the given writeable raw\n"
 
1425
    "stream. If the buffer_size is not given, it defaults to\n"
 
1426
    "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
 
1427
    );
 
1428
 
 
1429
static void
 
1430
_BufferedWriter_reset_buf(BufferedObject *self)
 
1431
{
 
1432
    self->write_pos = 0;
 
1433
    self->write_end = -1;
 
1434
}
 
1435
 
 
1436
static int
 
1437
BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
 
1438
{
 
1439
    /* TODO: properly deprecate max_buffer_size */
 
1440
    char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
 
1441
    Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
 
1442
    Py_ssize_t max_buffer_size = -1;
 
1443
    PyObject *raw;
 
1444
 
 
1445
    self->ok = 0;
 
1446
 
 
1447
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
 
1448
                                     &raw, &buffer_size, &max_buffer_size)) {
 
1449
        return -1;
 
1450
    }
 
1451
 
 
1452
    if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
 
1453
        return -1;
 
1454
 
 
1455
    Py_CLEAR(self->raw);
 
1456
    Py_INCREF(raw);
 
1457
    self->raw = raw;
 
1458
    self->readable = 0;
 
1459
    self->writable = 1;
 
1460
 
 
1461
    self->buffer_size = buffer_size;
 
1462
    if (_Buffered_init(self) < 0)
 
1463
        return -1;
 
1464
    _BufferedWriter_reset_buf(self);
 
1465
    self->pos = 0;
 
1466
 
 
1467
    self->ok = 1;
 
1468
    return 0;
 
1469
}
 
1470
 
 
1471
static Py_ssize_t
 
1472
_BufferedWriter_raw_write(BufferedObject *self, char *start, Py_ssize_t len)
 
1473
{
 
1474
    Py_buffer buf;
 
1475
    PyObject *memobj, *res;
 
1476
    Py_ssize_t n;
 
1477
    /* NOTE: the buffer needn't be released as its object is NULL. */
 
1478
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
 
1479
        return -1;
 
1480
    memobj = PyMemoryView_FromBuffer(&buf);
 
1481
    if (memobj == NULL)
 
1482
        return -1;
 
1483
    res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
 
1484
    Py_DECREF(memobj);
 
1485
    if (res == NULL)
 
1486
        return -1;
 
1487
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
 
1488
    Py_DECREF(res);
 
1489
    if (n < 0 || n > len) {
 
1490
        PyErr_Format(PyExc_IOError,
 
1491
                     "raw write() returned invalid length %zd "
 
1492
                     "(should have been between 0 and %zd)", n, len);
 
1493
        return -1;
 
1494
    }
 
1495
    if (n > 0 && self->abs_pos != -1)
 
1496
        self->abs_pos += n;
 
1497
    return n;
 
1498
}
 
1499
 
 
1500
/* `restore_pos` is 1 if we need to restore the raw stream position at
 
1501
   the end, 0 otherwise. */
 
1502
static PyObject *
 
1503
_BufferedWriter_flush_unlocked(BufferedObject *self, int restore_pos)
 
1504
{
 
1505
    Py_ssize_t written = 0;
 
1506
    Py_off_t n, rewind;
 
1507
 
 
1508
    if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
 
1509
        goto end;
 
1510
    /* First, rewind */
 
1511
    rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
 
1512
    if (rewind != 0) {
 
1513
        n = _Buffered_raw_seek(self, -rewind, 1);
 
1514
        if (n < 0) {
 
1515
            goto error;
 
1516
        }
 
1517
        self->raw_pos -= rewind;
 
1518
    }
 
1519
    while (self->write_pos < self->write_end) {
 
1520
        n = _BufferedWriter_raw_write(self,
 
1521
            self->buffer + self->write_pos,
 
1522
            Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
 
1523
                             Py_off_t, Py_ssize_t));
 
1524
        if (n == -1) {
 
1525
            Py_ssize_t *w = _Buffered_check_blocking_error();
 
1526
            if (w == NULL)
 
1527
                goto error;
 
1528
            self->write_pos += *w;
 
1529
            self->raw_pos = self->write_pos;
 
1530
            written += *w;
 
1531
            *w = written;
 
1532
            /* Already re-raised */
 
1533
            goto error;
 
1534
        }
 
1535
        self->write_pos += n;
 
1536
        self->raw_pos = self->write_pos;
 
1537
        written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
 
1538
    }
 
1539
 
 
1540
    if (restore_pos) {
 
1541
        Py_off_t forward = rewind - written;
 
1542
        if (forward != 0) {
 
1543
            n = _Buffered_raw_seek(self, forward, 1);
 
1544
            if (n < 0) {
 
1545
                goto error;
 
1546
            }
 
1547
            self->raw_pos += forward;
 
1548
        }
 
1549
    }
 
1550
    _BufferedWriter_reset_buf(self);
 
1551
 
 
1552
end:
 
1553
    Py_RETURN_NONE;
 
1554
 
 
1555
error:
 
1556
    return NULL;
 
1557
}
 
1558
 
 
1559
static PyObject *
 
1560
BufferedWriter_write(BufferedObject *self, PyObject *args)
 
1561
{
 
1562
    PyObject *res = NULL;
 
1563
    Py_buffer buf;
 
1564
    Py_ssize_t written, avail, remaining, n;
 
1565
 
 
1566
    CHECK_INITIALIZED(self)
 
1567
    if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
 
1568
        return NULL;
 
1569
    }
 
1570
 
 
1571
    if (BufferedIOMixin_closed(self)) {
 
1572
        PyErr_SetString(PyExc_ValueError, "write to closed file");
 
1573
        PyBuffer_Release(&buf);
 
1574
        return NULL;
 
1575
    }
 
1576
 
 
1577
    ENTER_BUFFERED(self)
 
1578
 
 
1579
    /* Fast path: the data to write can be fully buffered. */
 
1580
    if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
 
1581
        self->pos = 0;
 
1582
        self->raw_pos = 0;
 
1583
    }
 
1584
    avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
 
1585
    if (buf.len <= avail) {
 
1586
        memcpy(self->buffer + self->pos, buf.buf, buf.len);
 
1587
        if (!VALID_WRITE_BUFFER(self)) {
 
1588
            self->write_pos = self->pos;
 
1589
        }
 
1590
        ADJUST_POSITION(self, self->pos + buf.len);
 
1591
        if (self->pos > self->write_end)
 
1592
            self->write_end = self->pos;
 
1593
        written = buf.len;
 
1594
        goto end;
 
1595
    }
 
1596
 
 
1597
    /* First write the current buffer */
 
1598
    res = _BufferedWriter_flush_unlocked(self, 0);
 
1599
    if (res == NULL) {
 
1600
        Py_ssize_t *w = _Buffered_check_blocking_error();
 
1601
        if (w == NULL)
 
1602
            goto error;
 
1603
        if (self->readable)
 
1604
            _BufferedReader_reset_buf(self);
 
1605
        /* Make some place by shifting the buffer. */
 
1606
        assert(VALID_WRITE_BUFFER(self));
 
1607
        memmove(self->buffer, self->buffer + self->write_pos,
 
1608
                Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
 
1609
                                 Py_off_t, Py_ssize_t));
 
1610
        self->write_end -= self->write_pos;
 
1611
        self->raw_pos -= self->write_pos;
 
1612
        self->pos -= self->write_pos;
 
1613
        self->write_pos = 0;
 
1614
        avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
 
1615
                                 Py_off_t, Py_ssize_t);
 
1616
        if (buf.len <= avail) {
 
1617
            /* Everything can be buffered */
 
1618
            PyErr_Clear();
 
1619
            memcpy(self->buffer + self->write_end, buf.buf, buf.len);
 
1620
            self->write_end += buf.len;
 
1621
            written = buf.len;
 
1622
            goto end;
 
1623
        }
 
1624
        /* Buffer as much as possible. */
 
1625
        memcpy(self->buffer + self->write_end, buf.buf, avail);
 
1626
        self->write_end += avail;
 
1627
        /* Already re-raised */
 
1628
        *w = avail;
 
1629
        goto error;
 
1630
    }
 
1631
    Py_CLEAR(res);
 
1632
 
 
1633
    /* Then write buf itself. At this point the buffer has been emptied. */
 
1634
    remaining = buf.len;
 
1635
    written = 0;
 
1636
    while (remaining > self->buffer_size) {
 
1637
        n = _BufferedWriter_raw_write(
 
1638
            self, (char *) buf.buf + written, buf.len - written);
 
1639
        if (n == -1) {
 
1640
            Py_ssize_t *w = _Buffered_check_blocking_error();
 
1641
            if (w == NULL)
 
1642
                goto error;
 
1643
            written += *w;
 
1644
            remaining -= *w;
 
1645
            if (remaining > self->buffer_size) {
 
1646
                /* Can't buffer everything, still buffer as much as possible */
 
1647
                memcpy(self->buffer,
 
1648
                       (char *) buf.buf + written, self->buffer_size);
 
1649
                self->raw_pos = 0;
 
1650
                ADJUST_POSITION(self, self->buffer_size);
 
1651
                self->write_end = self->buffer_size;
 
1652
                *w = written + self->buffer_size;
 
1653
                /* Already re-raised */
 
1654
                goto error;
 
1655
            }
 
1656
            PyErr_Clear();
 
1657
            break;
 
1658
        }
 
1659
        written += n;
 
1660
        remaining -= n;
 
1661
    }
 
1662
    if (self->readable)
 
1663
        _BufferedReader_reset_buf(self);
 
1664
    if (remaining > 0) {
 
1665
        memcpy(self->buffer, (char *) buf.buf + written, remaining);
 
1666
        written += remaining;
 
1667
    }
 
1668
    self->write_pos = 0;
 
1669
    /* TODO: sanity check (remaining >= 0) */
 
1670
    self->write_end = remaining;
 
1671
    ADJUST_POSITION(self, remaining);
 
1672
    self->raw_pos = 0;
 
1673
 
 
1674
end:
 
1675
    res = PyLong_FromSsize_t(written);
 
1676
 
 
1677
error:
 
1678
    LEAVE_BUFFERED(self)
 
1679
    PyBuffer_Release(&buf);
 
1680
    return res;
 
1681
}
 
1682
 
 
1683
static PyMethodDef BufferedWriter_methods[] = {
 
1684
    /* BufferedIOMixin methods */
 
1685
    {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
 
1686
    {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
 
1687
    {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
 
1688
    {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
 
1689
    {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
 
1690
    {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
 
1691
 
 
1692
    {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
 
1693
    {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
 
1694
    {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
 
1695
    {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
 
1696
    {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
 
1697
    {NULL, NULL}
 
1698
};
 
1699
 
 
1700
static PyMemberDef BufferedWriter_members[] = {
 
1701
    {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
 
1702
    {NULL}
 
1703
};
 
1704
 
 
1705
static PyGetSetDef BufferedWriter_getset[] = {
 
1706
    {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
 
1707
    {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
 
1708
    {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
 
1709
    {0}
 
1710
};
 
1711
 
 
1712
 
 
1713
PyTypeObject PyBufferedWriter_Type = {
 
1714
    PyVarObject_HEAD_INIT(NULL, 0)
 
1715
    "_io.BufferedWriter",       /*tp_name*/
 
1716
    sizeof(BufferedObject),     /*tp_basicsize*/
 
1717
    0,                          /*tp_itemsize*/
 
1718
    (destructor)BufferedObject_dealloc,     /*tp_dealloc*/
 
1719
    0,                          /*tp_print*/
 
1720
    0,                          /*tp_getattr*/
 
1721
    0,                          /*tp_setattr*/
 
1722
    0,                          /*tp_compare */
 
1723
    0,                          /*tp_repr*/
 
1724
    0,                          /*tp_as_number*/
 
1725
    0,                          /*tp_as_sequence*/
 
1726
    0,                          /*tp_as_mapping*/
 
1727
    0,                          /*tp_hash */
 
1728
    0,                          /*tp_call*/
 
1729
    0,                          /*tp_str*/
 
1730
    0,                          /*tp_getattro*/
 
1731
    0,                          /*tp_setattro*/
 
1732
    0,                          /*tp_as_buffer*/
 
1733
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
 
1734
        | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
 
1735
    BufferedWriter_doc,         /* tp_doc */
 
1736
    (traverseproc)Buffered_traverse, /* tp_traverse */
 
1737
    (inquiry)Buffered_clear,    /* tp_clear */
 
1738
    0,                          /* tp_richcompare */
 
1739
    offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
 
1740
    0,                          /* tp_iter */
 
1741
    0,                          /* tp_iternext */
 
1742
    BufferedWriter_methods,     /* tp_methods */
 
1743
    BufferedWriter_members,     /* tp_members */
 
1744
    BufferedWriter_getset,      /* tp_getset */
 
1745
    0,                          /* tp_base */
 
1746
    0,                          /* tp_dict */
 
1747
    0,                          /* tp_descr_get */
 
1748
    0,                          /* tp_descr_set */
 
1749
    offsetof(BufferedObject, dict), /* tp_dictoffset */
 
1750
    (initproc)BufferedWriter_init, /* tp_init */
 
1751
    0,                          /* tp_alloc */
 
1752
    PyType_GenericNew,          /* tp_new */
 
1753
};
 
1754
 
 
1755
 
 
1756
 
 
1757
/*
 
1758
 * BufferedRWPair
 
1759
 */
 
1760
 
 
1761
PyDoc_STRVAR(BufferedRWPair_doc,
 
1762
    "A buffered reader and writer object together.\n"
 
1763
    "\n"
 
1764
    "A buffered reader object and buffered writer object put together to\n"
 
1765
    "form a sequential IO object that can read and write. This is typically\n"
 
1766
    "used with a socket or two-way pipe.\n"
 
1767
    "\n"
 
1768
    "reader and writer are RawIOBase objects that are readable and\n"
 
1769
    "writeable respectively. If the buffer_size is omitted it defaults to\n"
 
1770
    "DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered writer)\n"
 
1771
    "defaults to twice the buffer size.\n"
 
1772
    );
 
1773
 
 
1774
/* XXX The usefulness of this (compared to having two separate IO objects) is
 
1775
 * questionable.
 
1776
 */
 
1777
 
 
1778
typedef struct {
 
1779
    PyObject_HEAD
 
1780
    BufferedObject *reader;
 
1781
    BufferedObject *writer;
 
1782
    PyObject *dict;
 
1783
    PyObject *weakreflist;
 
1784
} BufferedRWPairObject;
 
1785
 
 
1786
static int
 
1787
BufferedRWPair_init(BufferedRWPairObject *self, PyObject *args,
 
1788
                     PyObject *kwds)
 
1789
{
 
1790
    PyObject *reader, *writer;
 
1791
    Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
 
1792
    Py_ssize_t max_buffer_size = -1;
 
1793
 
 
1794
    if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
 
1795
                          &buffer_size, &max_buffer_size)) {
 
1796
        return -1;
 
1797
    }
 
1798
 
 
1799
    if (_PyIOBase_checkReadable(reader, Py_True) == NULL)
 
1800
        return -1;
 
1801
    if (_PyIOBase_checkWritable(writer, Py_True) == NULL)
 
1802
        return -1;
 
1803
 
 
1804
    args = Py_BuildValue("(n)", buffer_size);
 
1805
    if (args == NULL) {
 
1806
        Py_CLEAR(self->reader);
 
1807
        return -1;
 
1808
    }
 
1809
    self->reader = (BufferedObject *)PyType_GenericNew(
 
1810
            &PyBufferedReader_Type, args, NULL);
 
1811
    Py_DECREF(args);
 
1812
    if (self->reader == NULL)
 
1813
        return -1;
 
1814
 
 
1815
    args = Py_BuildValue("(nn)", buffer_size, max_buffer_size);
 
1816
    if (args == NULL) {
 
1817
        Py_CLEAR(self->reader);
 
1818
        return -1;
 
1819
    }
 
1820
    self->writer = (BufferedObject *)PyType_GenericNew(
 
1821
            &PyBufferedWriter_Type, args, NULL);
 
1822
    Py_DECREF(args);
 
1823
    if (self->writer == NULL) {
 
1824
        Py_CLEAR(self->reader);
 
1825
        return -1;
 
1826
    }
 
1827
    return 0;
 
1828
}
 
1829
 
 
1830
static int
 
1831
BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg)
 
1832
{
 
1833
    Py_VISIT(self->dict);
 
1834
    return 0;
 
1835
}
 
1836
 
 
1837
static int
 
1838
BufferedRWPair_clear(BufferedRWPairObject *self)
 
1839
{
 
1840
    Py_CLEAR(self->reader);
 
1841
    Py_CLEAR(self->writer);
 
1842
    Py_CLEAR(self->dict);
 
1843
    return 0;
 
1844
}
 
1845
 
 
1846
static void
 
1847
BufferedRWPair_dealloc(BufferedRWPairObject *self)
 
1848
{
 
1849
    _PyObject_GC_UNTRACK(self);
 
1850
    Py_CLEAR(self->reader);
 
1851
    Py_CLEAR(self->writer);
 
1852
    Py_CLEAR(self->dict);
 
1853
    Py_TYPE(self)->tp_free((PyObject *) self);
 
1854
}
 
1855
 
 
1856
static PyObject *
 
1857
_forward_call(BufferedObject *self, const char *name, PyObject *args)
 
1858
{
 
1859
    PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
 
1860
    PyObject *ret;
 
1861
 
 
1862
    if (func == NULL) {
 
1863
        PyErr_SetString(PyExc_AttributeError, name);
 
1864
        return NULL;
 
1865
    }
 
1866
 
 
1867
    ret = PyObject_CallObject(func, args);
 
1868
    Py_DECREF(func);
 
1869
    return ret;
 
1870
}
 
1871
 
 
1872
static PyObject *
 
1873
BufferedRWPair_read(BufferedRWPairObject *self, PyObject *args)
 
1874
{
 
1875
    return _forward_call(self->reader, "read", args);
 
1876
}
 
1877
 
 
1878
static PyObject *
 
1879
BufferedRWPair_peek(BufferedRWPairObject *self, PyObject *args)
 
1880
{
 
1881
    return _forward_call(self->reader, "peek", args);
 
1882
}
 
1883
 
 
1884
static PyObject *
 
1885
BufferedRWPair_read1(BufferedRWPairObject *self, PyObject *args)
 
1886
{
 
1887
    return _forward_call(self->reader, "read1", args);
 
1888
}
 
1889
 
 
1890
static PyObject *
 
1891
BufferedRWPair_write(BufferedRWPairObject *self, PyObject *args)
 
1892
{
 
1893
    return _forward_call(self->writer, "write", args);
 
1894
}
 
1895
 
 
1896
static PyObject *
 
1897
BufferedRWPair_flush(BufferedRWPairObject *self, PyObject *args)
 
1898
{
 
1899
    return _forward_call(self->writer, "flush", args);
 
1900
}
 
1901
 
 
1902
static PyObject *
 
1903
BufferedRWPair_readable(BufferedRWPairObject *self, PyObject *args)
 
1904
{
 
1905
    return _forward_call(self->reader, "readable", args);
 
1906
}
 
1907
 
 
1908
static PyObject *
 
1909
BufferedRWPair_writable(BufferedRWPairObject *self, PyObject *args)
 
1910
{
 
1911
    return _forward_call(self->writer, "writable", args);
 
1912
}
 
1913
 
 
1914
static PyObject *
 
1915
BufferedRWPair_close(BufferedRWPairObject *self, PyObject *args)
 
1916
{
 
1917
    PyObject *ret = _forward_call(self->writer, "close", args);
 
1918
    if (ret == NULL)
 
1919
        return NULL;
 
1920
    Py_DECREF(ret);
 
1921
 
 
1922
    return _forward_call(self->reader, "close", args);
 
1923
}
 
1924
 
 
1925
static PyObject *
 
1926
BufferedRWPair_isatty(BufferedRWPairObject *self, PyObject *args)
 
1927
{
 
1928
    PyObject *ret = _forward_call(self->writer, "isatty", args);
 
1929
 
 
1930
    if (ret != Py_False) {
 
1931
        /* either True or exception */
 
1932
        return ret;
 
1933
    }
 
1934
    Py_DECREF(ret);
 
1935
 
 
1936
    return _forward_call(self->reader, "isatty", args);
 
1937
}
 
1938
 
 
1939
 
 
1940
static PyMethodDef BufferedRWPair_methods[] = {
 
1941
    {"read", (PyCFunction)BufferedRWPair_read, METH_VARARGS},
 
1942
    {"peek", (PyCFunction)BufferedRWPair_peek, METH_VARARGS},
 
1943
    {"read1", (PyCFunction)BufferedRWPair_read1, METH_VARARGS},
 
1944
    {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
 
1945
 
 
1946
    {"write", (PyCFunction)BufferedRWPair_write, METH_VARARGS},
 
1947
    {"flush", (PyCFunction)BufferedRWPair_flush, METH_NOARGS},
 
1948
 
 
1949
    {"readable", (PyCFunction)BufferedRWPair_readable, METH_NOARGS},
 
1950
    {"writable", (PyCFunction)BufferedRWPair_writable, METH_NOARGS},
 
1951
 
 
1952
    {"close", (PyCFunction)BufferedRWPair_close, METH_NOARGS},
 
1953
    {"isatty", (PyCFunction)BufferedRWPair_isatty, METH_NOARGS},
 
1954
 
 
1955
    {NULL, NULL}
 
1956
};
 
1957
 
 
1958
PyTypeObject PyBufferedRWPair_Type = {
 
1959
    PyVarObject_HEAD_INIT(NULL, 0)
 
1960
    "_io.BufferedRWPair",       /*tp_name*/
 
1961
    sizeof(BufferedRWPairObject), /*tp_basicsize*/
 
1962
    0,                          /*tp_itemsize*/
 
1963
    (destructor)BufferedRWPair_dealloc,     /*tp_dealloc*/
 
1964
    0,                          /*tp_print*/
 
1965
    0,                          /*tp_getattr*/
 
1966
    0,                          /*tp_setattr*/
 
1967
    0,                          /*tp_compare */
 
1968
    0,                          /*tp_repr*/
 
1969
    0,                          /*tp_as_number*/
 
1970
    0,                          /*tp_as_sequence*/
 
1971
    0,                          /*tp_as_mapping*/
 
1972
    0,                          /*tp_hash */
 
1973
    0,                          /*tp_call*/
 
1974
    0,                          /*tp_str*/
 
1975
    0,                          /*tp_getattro*/
 
1976
    0,                          /*tp_setattro*/
 
1977
    0,                          /*tp_as_buffer*/
 
1978
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
 
1979
        | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
 
1980
    BufferedRWPair_doc,         /* tp_doc */
 
1981
    (traverseproc)BufferedRWPair_traverse, /* tp_traverse */
 
1982
    (inquiry)BufferedRWPair_clear, /* tp_clear */
 
1983
    0,                          /* tp_richcompare */
 
1984
    offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/
 
1985
    0,                          /* tp_iter */
 
1986
    0,                          /* tp_iternext */
 
1987
    BufferedRWPair_methods,     /* tp_methods */
 
1988
    0,                          /* tp_members */
 
1989
    0,                          /* tp_getset */
 
1990
    0,                          /* tp_base */
 
1991
    0,                          /* tp_dict */
 
1992
    0,                          /* tp_descr_get */
 
1993
    0,                          /* tp_descr_set */
 
1994
    offsetof(BufferedRWPairObject, dict), /* tp_dictoffset */
 
1995
    (initproc)BufferedRWPair_init, /* tp_init */
 
1996
    0,                          /* tp_alloc */
 
1997
    PyType_GenericNew,          /* tp_new */
 
1998
};
 
1999
 
 
2000
 
 
2001
 
 
2002
/*
 
2003
 * BufferedRandom
 
2004
 */
 
2005
 
 
2006
PyDoc_STRVAR(BufferedRandom_doc,
 
2007
    "A buffered interface to random access streams.\n"
 
2008
    "\n"
 
2009
    "The constructor creates a reader and writer for a seekable stream,\n"
 
2010
    "raw, given in the first argument. If the buffer_size is omitted it\n"
 
2011
    "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
 
2012
    );
 
2013
 
 
2014
static int
 
2015
BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
 
2016
{
 
2017
    char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
 
2018
    Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
 
2019
    Py_ssize_t max_buffer_size = -1;
 
2020
    PyObject *raw;
 
2021
 
 
2022
    self->ok = 0;
 
2023
 
 
2024
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
 
2025
                                     &raw, &buffer_size, &max_buffer_size)) {
 
2026
        return -1;
 
2027
    }
 
2028
 
 
2029
    if (_PyIOBase_checkSeekable(raw, Py_True) == NULL)
 
2030
        return -1;
 
2031
    if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
 
2032
        return -1;
 
2033
    if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
 
2034
        return -1;
 
2035
 
 
2036
    Py_CLEAR(self->raw);
 
2037
    Py_INCREF(raw);
 
2038
    self->raw = raw;
 
2039
    self->buffer_size = buffer_size;
 
2040
    self->readable = 1;
 
2041
    self->writable = 1;
 
2042
 
 
2043
    if (_Buffered_init(self) < 0)
 
2044
        return -1;
 
2045
    _BufferedReader_reset_buf(self);
 
2046
    _BufferedWriter_reset_buf(self);
 
2047
    self->pos = 0;
 
2048
 
 
2049
    self->ok = 1;
 
2050
    return 0;
 
2051
}
 
2052
 
 
2053
static PyMethodDef BufferedRandom_methods[] = {
 
2054
    /* BufferedIOMixin methods */
 
2055
    {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
 
2056
    {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
 
2057
    {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
 
2058
    {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
 
2059
    {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
 
2060
    {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
 
2061
 
 
2062
    {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
 
2063
 
 
2064
    {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
 
2065
    {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
 
2066
    {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
 
2067
    {"read", (PyCFunction)Buffered_read, METH_VARARGS},
 
2068
    {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
 
2069
    {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
 
2070
    {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
 
2071
    {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
 
2072
    {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
 
2073
    {NULL, NULL}
 
2074
};
 
2075
 
 
2076
static PyMemberDef BufferedRandom_members[] = {
 
2077
    {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
 
2078
    {NULL}
 
2079
};
 
2080
 
 
2081
static PyGetSetDef BufferedRandom_getset[] = {
 
2082
    {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
 
2083
    {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
 
2084
    {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
 
2085
    {0}
 
2086
};
 
2087
 
 
2088
 
 
2089
PyTypeObject PyBufferedRandom_Type = {
 
2090
    PyVarObject_HEAD_INIT(NULL, 0)
 
2091
    "_io.BufferedRandom",       /*tp_name*/
 
2092
    sizeof(BufferedObject),     /*tp_basicsize*/
 
2093
    0,                          /*tp_itemsize*/
 
2094
    (destructor)BufferedObject_dealloc,     /*tp_dealloc*/
 
2095
    0,                          /*tp_print*/
 
2096
    0,                          /*tp_getattr*/
 
2097
    0,                          /*tp_setattr*/
 
2098
    0,                          /*tp_compare */
 
2099
    0,                          /*tp_repr*/
 
2100
    0,                          /*tp_as_number*/
 
2101
    0,                          /*tp_as_sequence*/
 
2102
    0,                          /*tp_as_mapping*/
 
2103
    0,                          /*tp_hash */
 
2104
    0,                          /*tp_call*/
 
2105
    0,                          /*tp_str*/
 
2106
    0,                          /*tp_getattro*/
 
2107
    0,                          /*tp_setattro*/
 
2108
    0,                          /*tp_as_buffer*/
 
2109
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
 
2110
        | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
 
2111
    BufferedRandom_doc,         /* tp_doc */
 
2112
    (traverseproc)Buffered_traverse, /* tp_traverse */
 
2113
    (inquiry)Buffered_clear,    /* tp_clear */
 
2114
    0,                          /* tp_richcompare */
 
2115
    offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
 
2116
    0,                          /* tp_iter */
 
2117
    (iternextfunc)Buffered_iternext, /* tp_iternext */
 
2118
    BufferedRandom_methods,     /* tp_methods */
 
2119
    BufferedRandom_members,     /* tp_members */
 
2120
    BufferedRandom_getset,      /* tp_getset */
 
2121
    0,                          /* tp_base */
 
2122
    0,                          /*tp_dict*/
 
2123
    0,                          /* tp_descr_get */
 
2124
    0,                          /* tp_descr_set */
 
2125
    offsetof(BufferedObject, dict), /*tp_dictoffset*/
 
2126
    (initproc)BufferedRandom_init, /* tp_init */
 
2127
    0,                          /* tp_alloc */
 
2128
    PyType_GenericNew,          /* tp_new */
 
2129
};
 
2130