|
1 #include "Python.h" |
|
2 |
|
3 typedef struct { |
|
4 PyObject_HEAD |
|
5 char *buf; |
|
6 Py_ssize_t pos; |
|
7 Py_ssize_t string_size; |
|
8 size_t buf_size; |
|
9 } BytesIOObject; |
|
10 |
|
11 #define CHECK_CLOSED(self) \ |
|
12 if ((self)->buf == NULL) { \ |
|
13 PyErr_SetString(PyExc_ValueError, \ |
|
14 "I/O operation on closed file."); \ |
|
15 return NULL; \ |
|
16 } |
|
17 |
|
18 /* Internal routine to get a line from the buffer of a BytesIO |
|
19 object. Returns the length between the current position to the |
|
20 next newline character. */ |
|
21 static Py_ssize_t |
|
22 get_line(BytesIOObject *self, char **output) |
|
23 { |
|
24 char *n; |
|
25 const char *str_end; |
|
26 Py_ssize_t len; |
|
27 |
|
28 assert(self->buf != NULL); |
|
29 |
|
30 /* Move to the end of the line, up to the end of the string, s. */ |
|
31 str_end = self->buf + self->string_size; |
|
32 for (n = self->buf + self->pos; |
|
33 n < str_end && *n != '\n'; |
|
34 n++); |
|
35 |
|
36 /* Skip the newline character */ |
|
37 if (n < str_end) |
|
38 n++; |
|
39 |
|
40 /* Get the length from the current position to the end of the line. */ |
|
41 len = n - (self->buf + self->pos); |
|
42 *output = self->buf + self->pos; |
|
43 |
|
44 assert(len >= 0); |
|
45 assert(self->pos < PY_SSIZE_T_MAX - len); |
|
46 self->pos += len; |
|
47 |
|
48 return len; |
|
49 } |
|
50 |
|
51 /* Internal routine for changing the size of the buffer of BytesIO objects. |
|
52 The caller should ensure that the 'size' argument is non-negative. Returns |
|
53 0 on success, -1 otherwise. */ |
|
54 static int |
|
55 resize_buffer(BytesIOObject *self, size_t size) |
|
56 { |
|
57 /* Here, unsigned types are used to avoid dealing with signed integer |
|
58 overflow, which is undefined in C. */ |
|
59 size_t alloc = self->buf_size; |
|
60 char *new_buf = NULL; |
|
61 |
|
62 assert(self->buf != NULL); |
|
63 |
|
64 /* For simplicity, stay in the range of the signed type. Anyway, Python |
|
65 doesn't allow strings to be longer than this. */ |
|
66 if (size > PY_SSIZE_T_MAX) |
|
67 goto overflow; |
|
68 |
|
69 if (size < alloc / 2) { |
|
70 /* Major downsize; resize down to exact size. */ |
|
71 alloc = size + 1; |
|
72 } |
|
73 else if (size < alloc) { |
|
74 /* Within allocated size; quick exit */ |
|
75 return 0; |
|
76 } |
|
77 else if (size <= alloc * 1.125) { |
|
78 /* Moderate upsize; overallocate similar to list_resize() */ |
|
79 alloc = size + (size >> 3) + (size < 9 ? 3 : 6); |
|
80 } |
|
81 else { |
|
82 /* Major upsize; resize up to exact size */ |
|
83 alloc = size + 1; |
|
84 } |
|
85 |
|
86 if (alloc > ((size_t)-1) / sizeof(char)) |
|
87 goto overflow; |
|
88 new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char)); |
|
89 if (new_buf == NULL) { |
|
90 PyErr_NoMemory(); |
|
91 return -1; |
|
92 } |
|
93 self->buf_size = alloc; |
|
94 self->buf = new_buf; |
|
95 |
|
96 return 0; |
|
97 |
|
98 overflow: |
|
99 PyErr_SetString(PyExc_OverflowError, |
|
100 "new buffer size too large"); |
|
101 return -1; |
|
102 } |
|
103 |
|
104 /* Internal routine for writing a string of bytes to the buffer of a BytesIO |
|
105 object. Returns the number of bytes wrote, or -1 on error. */ |
|
106 static Py_ssize_t |
|
107 write_bytes(BytesIOObject *self, const char *bytes, Py_ssize_t len) |
|
108 { |
|
109 assert(self->buf != NULL); |
|
110 assert(self->pos >= 0); |
|
111 assert(len >= 0); |
|
112 |
|
113 if ((size_t)self->pos + len > self->buf_size) { |
|
114 if (resize_buffer(self, (size_t)self->pos + len) < 0) |
|
115 return -1; |
|
116 } |
|
117 |
|
118 if (self->pos > self->string_size) { |
|
119 /* In case of overseek, pad with null bytes the buffer region between |
|
120 the end of stream and the current position. |
|
121 |
|
122 0 lo string_size hi |
|
123 | |<---used--->|<----------available----------->| |
|
124 | | <--to pad-->|<---to write---> | |
|
125 0 buf position |
|
126 */ |
|
127 memset(self->buf + self->string_size, '\0', |
|
128 (self->pos - self->string_size) * sizeof(char)); |
|
129 } |
|
130 |
|
131 /* Copy the data to the internal buffer, overwriting some of the existing |
|
132 data if self->pos < self->string_size. */ |
|
133 memcpy(self->buf + self->pos, bytes, len); |
|
134 self->pos += len; |
|
135 |
|
136 /* Set the new length of the internal string if it has changed. */ |
|
137 if (self->string_size < self->pos) { |
|
138 self->string_size = self->pos; |
|
139 } |
|
140 |
|
141 return len; |
|
142 } |
|
143 |
|
144 static PyObject * |
|
145 bytesio_get_closed(BytesIOObject *self) |
|
146 { |
|
147 if (self->buf == NULL) |
|
148 Py_RETURN_TRUE; |
|
149 else |
|
150 Py_RETURN_FALSE; |
|
151 } |
|
152 |
|
153 /* Generic getter for the writable, readable and seekable properties */ |
|
154 static PyObject * |
|
155 return_true(BytesIOObject *self) |
|
156 { |
|
157 Py_RETURN_TRUE; |
|
158 } |
|
159 |
|
160 PyDoc_STRVAR(flush_doc, |
|
161 "flush() -> None. Does nothing."); |
|
162 |
|
163 static PyObject * |
|
164 bytesio_flush(BytesIOObject *self) |
|
165 { |
|
166 Py_RETURN_NONE; |
|
167 } |
|
168 |
|
169 PyDoc_STRVAR(getval_doc, |
|
170 "getvalue() -> bytes.\n" |
|
171 "\n" |
|
172 "Retrieve the entire contents of the BytesIO object."); |
|
173 |
|
174 static PyObject * |
|
175 bytesio_getvalue(BytesIOObject *self) |
|
176 { |
|
177 CHECK_CLOSED(self); |
|
178 return PyString_FromStringAndSize(self->buf, self->string_size); |
|
179 } |
|
180 |
|
181 PyDoc_STRVAR(isatty_doc, |
|
182 "isatty() -> False.\n" |
|
183 "\n" |
|
184 "Always returns False since BytesIO objects are not connected\n" |
|
185 "to a tty-like device."); |
|
186 |
|
187 static PyObject * |
|
188 bytesio_isatty(BytesIOObject *self) |
|
189 { |
|
190 CHECK_CLOSED(self); |
|
191 Py_RETURN_FALSE; |
|
192 } |
|
193 |
|
194 PyDoc_STRVAR(tell_doc, |
|
195 "tell() -> current file position, an integer\n"); |
|
196 |
|
197 static PyObject * |
|
198 bytesio_tell(BytesIOObject *self) |
|
199 { |
|
200 CHECK_CLOSED(self); |
|
201 return PyInt_FromSsize_t(self->pos); |
|
202 } |
|
203 |
|
204 PyDoc_STRVAR(read_doc, |
|
205 "read([size]) -> read at most size bytes, returned as a string.\n" |
|
206 "\n" |
|
207 "If the size argument is negative, read until EOF is reached.\n" |
|
208 "Return an empty string at EOF."); |
|
209 |
|
210 static PyObject * |
|
211 bytesio_read(BytesIOObject *self, PyObject *args) |
|
212 { |
|
213 Py_ssize_t size, n; |
|
214 char *output; |
|
215 PyObject *arg = Py_None; |
|
216 |
|
217 CHECK_CLOSED(self); |
|
218 |
|
219 if (!PyArg_ParseTuple(args, "|O:read", &arg)) |
|
220 return NULL; |
|
221 |
|
222 if (PyInt_Check(arg)) { |
|
223 size = PyInt_AsSsize_t(arg); |
|
224 if (size == -1 && PyErr_Occurred()) |
|
225 return NULL; |
|
226 } |
|
227 else if (arg == Py_None) { |
|
228 /* Read until EOF is reached, by default. */ |
|
229 size = -1; |
|
230 } |
|
231 else { |
|
232 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", |
|
233 Py_TYPE(arg)->tp_name); |
|
234 return NULL; |
|
235 } |
|
236 |
|
237 /* adjust invalid sizes */ |
|
238 n = self->string_size - self->pos; |
|
239 if (size < 0 || size > n) { |
|
240 size = n; |
|
241 if (size < 0) |
|
242 size = 0; |
|
243 } |
|
244 |
|
245 assert(self->buf != NULL); |
|
246 output = self->buf + self->pos; |
|
247 self->pos += size; |
|
248 |
|
249 return PyString_FromStringAndSize(output, size); |
|
250 } |
|
251 |
|
252 |
|
253 PyDoc_STRVAR(read1_doc, |
|
254 "read1(size) -> read at most size bytes, returned as a string.\n" |
|
255 "\n" |
|
256 "If the size argument is negative or omitted, read until EOF is reached.\n" |
|
257 "Return an empty string at EOF."); |
|
258 |
|
259 static PyObject * |
|
260 bytesio_read1(BytesIOObject *self, PyObject *n) |
|
261 { |
|
262 PyObject *arg, *res; |
|
263 |
|
264 arg = PyTuple_Pack(1, n); |
|
265 if (arg == NULL) |
|
266 return NULL; |
|
267 res = bytesio_read(self, arg); |
|
268 Py_DECREF(arg); |
|
269 return res; |
|
270 } |
|
271 |
|
272 PyDoc_STRVAR(readline_doc, |
|
273 "readline([size]) -> next line from the file, as a string.\n" |
|
274 "\n" |
|
275 "Retain newline. A non-negative size argument limits the maximum\n" |
|
276 "number of bytes to return (an incomplete line may be returned then).\n" |
|
277 "Return an empty string at EOF.\n"); |
|
278 |
|
279 static PyObject * |
|
280 bytesio_readline(BytesIOObject *self, PyObject *args) |
|
281 { |
|
282 Py_ssize_t size, n; |
|
283 char *output; |
|
284 PyObject *arg = Py_None; |
|
285 |
|
286 CHECK_CLOSED(self); |
|
287 |
|
288 if (!PyArg_ParseTuple(args, "|O:readline", &arg)) |
|
289 return NULL; |
|
290 |
|
291 if (PyInt_Check(arg)) { |
|
292 size = PyInt_AsSsize_t(arg); |
|
293 if (size == -1 && PyErr_Occurred()) |
|
294 return NULL; |
|
295 } |
|
296 else if (arg == Py_None) { |
|
297 /* No size limit, by default. */ |
|
298 size = -1; |
|
299 } |
|
300 else { |
|
301 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", |
|
302 Py_TYPE(arg)->tp_name); |
|
303 return NULL; |
|
304 } |
|
305 |
|
306 n = get_line(self, &output); |
|
307 |
|
308 if (size >= 0 && size < n) { |
|
309 size = n - size; |
|
310 n -= size; |
|
311 self->pos -= size; |
|
312 } |
|
313 |
|
314 return PyString_FromStringAndSize(output, n); |
|
315 } |
|
316 |
|
317 PyDoc_STRVAR(readlines_doc, |
|
318 "readlines([size]) -> list of strings, each a line from the file.\n" |
|
319 "\n" |
|
320 "Call readline() repeatedly and return a list of the lines so read.\n" |
|
321 "The optional size argument, if given, is an approximate bound on the\n" |
|
322 "total number of bytes in the lines returned.\n"); |
|
323 |
|
324 static PyObject * |
|
325 bytesio_readlines(BytesIOObject *self, PyObject *args) |
|
326 { |
|
327 Py_ssize_t maxsize, size, n; |
|
328 PyObject *result, *line; |
|
329 char *output; |
|
330 PyObject *arg = Py_None; |
|
331 |
|
332 CHECK_CLOSED(self); |
|
333 |
|
334 if (!PyArg_ParseTuple(args, "|O:readlines", &arg)) |
|
335 return NULL; |
|
336 |
|
337 if (PyInt_Check(arg)) { |
|
338 maxsize = PyInt_AsSsize_t(arg); |
|
339 if (maxsize == -1 && PyErr_Occurred()) |
|
340 return NULL; |
|
341 } |
|
342 else if (arg == Py_None) { |
|
343 /* No size limit, by default. */ |
|
344 maxsize = -1; |
|
345 } |
|
346 else { |
|
347 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", |
|
348 Py_TYPE(arg)->tp_name); |
|
349 return NULL; |
|
350 } |
|
351 |
|
352 size = 0; |
|
353 result = PyList_New(0); |
|
354 if (!result) |
|
355 return NULL; |
|
356 |
|
357 while ((n = get_line(self, &output)) != 0) { |
|
358 line = PyString_FromStringAndSize(output, n); |
|
359 if (!line) |
|
360 goto on_error; |
|
361 if (PyList_Append(result, line) == -1) { |
|
362 Py_DECREF(line); |
|
363 goto on_error; |
|
364 } |
|
365 Py_DECREF(line); |
|
366 size += n; |
|
367 if (maxsize > 0 && size >= maxsize) |
|
368 break; |
|
369 } |
|
370 return result; |
|
371 |
|
372 on_error: |
|
373 Py_DECREF(result); |
|
374 return NULL; |
|
375 } |
|
376 |
|
377 PyDoc_STRVAR(readinto_doc, |
|
378 "readinto(bytearray) -> int. Read up to len(b) bytes into b.\n" |
|
379 "\n" |
|
380 "Returns number of bytes read (0 for EOF), or None if the object\n" |
|
381 "is set not to block as has no data to read."); |
|
382 |
|
383 static PyObject * |
|
384 bytesio_readinto(BytesIOObject *self, PyObject *buffer) |
|
385 { |
|
386 void *raw_buffer; |
|
387 Py_ssize_t len; |
|
388 |
|
389 CHECK_CLOSED(self); |
|
390 |
|
391 if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1) |
|
392 return NULL; |
|
393 |
|
394 if (self->pos + len > self->string_size) |
|
395 len = self->string_size - self->pos; |
|
396 |
|
397 memcpy(raw_buffer, self->buf + self->pos, len); |
|
398 assert(self->pos + len < PY_SSIZE_T_MAX); |
|
399 assert(len >= 0); |
|
400 self->pos += len; |
|
401 |
|
402 return PyInt_FromSsize_t(len); |
|
403 } |
|
404 |
|
405 PyDoc_STRVAR(truncate_doc, |
|
406 "truncate([size]) -> int. Truncate the file to at most size bytes.\n" |
|
407 "\n" |
|
408 "Size defaults to the current file position, as returned by tell().\n" |
|
409 "Returns the new size. Imply an absolute seek to the position size."); |
|
410 |
|
411 static PyObject * |
|
412 bytesio_truncate(BytesIOObject *self, PyObject *args) |
|
413 { |
|
414 Py_ssize_t size; |
|
415 PyObject *arg = Py_None; |
|
416 |
|
417 CHECK_CLOSED(self); |
|
418 |
|
419 if (!PyArg_ParseTuple(args, "|O:truncate", &arg)) |
|
420 return NULL; |
|
421 |
|
422 if (PyInt_Check(arg)) { |
|
423 size = PyInt_AsSsize_t(arg); |
|
424 if (size == -1 && PyErr_Occurred()) |
|
425 return NULL; |
|
426 } |
|
427 else if (arg == Py_None) { |
|
428 /* Truncate to current position if no argument is passed. */ |
|
429 size = self->pos; |
|
430 } |
|
431 else { |
|
432 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", |
|
433 Py_TYPE(arg)->tp_name); |
|
434 return NULL; |
|
435 } |
|
436 |
|
437 if (size < 0) { |
|
438 PyErr_Format(PyExc_ValueError, |
|
439 "negative size value %zd", size); |
|
440 return NULL; |
|
441 } |
|
442 |
|
443 if (size < self->string_size) { |
|
444 self->string_size = size; |
|
445 if (resize_buffer(self, size) < 0) |
|
446 return NULL; |
|
447 } |
|
448 self->pos = size; |
|
449 |
|
450 return PyInt_FromSsize_t(size); |
|
451 } |
|
452 |
|
453 static PyObject * |
|
454 bytesio_iternext(BytesIOObject *self) |
|
455 { |
|
456 char *next; |
|
457 Py_ssize_t n; |
|
458 |
|
459 CHECK_CLOSED(self); |
|
460 |
|
461 n = get_line(self, &next); |
|
462 |
|
463 if (!next || n == 0) |
|
464 return NULL; |
|
465 |
|
466 return PyString_FromStringAndSize(next, n); |
|
467 } |
|
468 |
|
469 PyDoc_STRVAR(seek_doc, |
|
470 "seek(pos, whence=0) -> int. Change stream position.\n" |
|
471 "\n" |
|
472 "Seek to byte offset pos relative to position indicated by whence:\n" |
|
473 " 0 Start of stream (the default). pos should be >= 0;\n" |
|
474 " 1 Current position - pos may be negative;\n" |
|
475 " 2 End of stream - pos usually negative.\n" |
|
476 "Returns the new absolute position."); |
|
477 |
|
478 static PyObject * |
|
479 bytesio_seek(BytesIOObject *self, PyObject *args) |
|
480 { |
|
481 PyObject *pos_obj, *mode_obj; |
|
482 Py_ssize_t pos; |
|
483 int mode = 0; |
|
484 |
|
485 CHECK_CLOSED(self); |
|
486 |
|
487 /* Special-case for 2.x to prevent floats from passing through. |
|
488 This only needed to make a test in test_io succeed. */ |
|
489 if (!PyArg_UnpackTuple(args, "seek", 1, 2, &pos_obj, &mode_obj)) |
|
490 return NULL; |
|
491 if (PyFloat_Check(pos_obj)) { |
|
492 PyErr_SetString(PyExc_TypeError, |
|
493 "position argument must be an integer"); |
|
494 return NULL; |
|
495 } |
|
496 |
|
497 if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode)) |
|
498 return NULL; |
|
499 |
|
500 if (pos < 0 && mode == 0) { |
|
501 PyErr_Format(PyExc_ValueError, |
|
502 "negative seek value %zd", pos); |
|
503 return NULL; |
|
504 } |
|
505 |
|
506 /* mode 0: offset relative to beginning of the string. |
|
507 mode 1: offset relative to current position. |
|
508 mode 2: offset relative the end of the string. */ |
|
509 if (mode == 1) { |
|
510 if (pos > PY_SSIZE_T_MAX - self->pos) { |
|
511 PyErr_SetString(PyExc_OverflowError, |
|
512 "new position too large"); |
|
513 return NULL; |
|
514 } |
|
515 pos += self->pos; |
|
516 } |
|
517 else if (mode == 2) { |
|
518 if (pos > PY_SSIZE_T_MAX - self->string_size) { |
|
519 PyErr_SetString(PyExc_OverflowError, |
|
520 "new position too large"); |
|
521 return NULL; |
|
522 } |
|
523 pos += self->string_size; |
|
524 } |
|
525 else if (mode != 0) { |
|
526 PyErr_Format(PyExc_ValueError, |
|
527 "invalid whence (%i, should be 0, 1 or 2)", mode); |
|
528 return NULL; |
|
529 } |
|
530 |
|
531 if (pos < 0) |
|
532 pos = 0; |
|
533 self->pos = pos; |
|
534 |
|
535 return PyInt_FromSsize_t(self->pos); |
|
536 } |
|
537 |
|
538 PyDoc_STRVAR(write_doc, |
|
539 "write(bytes) -> int. Write bytes to file.\n" |
|
540 "\n" |
|
541 "Return the number of bytes written."); |
|
542 |
|
543 static PyObject * |
|
544 bytesio_write(BytesIOObject *self, PyObject *obj) |
|
545 { |
|
546 const char *bytes; |
|
547 Py_ssize_t size; |
|
548 Py_ssize_t n = 0; |
|
549 |
|
550 CHECK_CLOSED(self); |
|
551 |
|
552 /* Special-case in 2.x to prevent unicode objects to pass through. */ |
|
553 if (PyUnicode_Check(obj)) { |
|
554 PyErr_SetString(PyExc_TypeError, |
|
555 "expecting a bytes object, got unicode"); |
|
556 return NULL; |
|
557 } |
|
558 |
|
559 if (PyObject_AsReadBuffer(obj, (void *)&bytes, &size) < 0) |
|
560 return NULL; |
|
561 |
|
562 if (size != 0) { |
|
563 n = write_bytes(self, bytes, size); |
|
564 if (n < 0) |
|
565 return NULL; |
|
566 } |
|
567 |
|
568 return PyInt_FromSsize_t(n); |
|
569 } |
|
570 |
|
571 PyDoc_STRVAR(writelines_doc, |
|
572 "writelines(sequence_of_strings) -> None. Write strings to the file.\n" |
|
573 "\n" |
|
574 "Note that newlines are not added. The sequence can be any iterable\n" |
|
575 "object producing strings. This is equivalent to calling write() for\n" |
|
576 "each string."); |
|
577 |
|
578 static PyObject * |
|
579 bytesio_writelines(BytesIOObject *self, PyObject *v) |
|
580 { |
|
581 PyObject *it, *item; |
|
582 PyObject *ret; |
|
583 |
|
584 CHECK_CLOSED(self); |
|
585 |
|
586 it = PyObject_GetIter(v); |
|
587 if (it == NULL) |
|
588 return NULL; |
|
589 |
|
590 while ((item = PyIter_Next(it)) != NULL) { |
|
591 ret = bytesio_write(self, item); |
|
592 Py_DECREF(item); |
|
593 if (ret == NULL) { |
|
594 Py_DECREF(it); |
|
595 return NULL; |
|
596 } |
|
597 Py_DECREF(ret); |
|
598 } |
|
599 Py_DECREF(it); |
|
600 |
|
601 /* See if PyIter_Next failed */ |
|
602 if (PyErr_Occurred()) |
|
603 return NULL; |
|
604 |
|
605 Py_RETURN_NONE; |
|
606 } |
|
607 |
|
608 PyDoc_STRVAR(close_doc, |
|
609 "close() -> None. Disable all I/O operations."); |
|
610 |
|
611 static PyObject * |
|
612 bytesio_close(BytesIOObject *self) |
|
613 { |
|
614 if (self->buf != NULL) { |
|
615 PyMem_Free(self->buf); |
|
616 self->buf = NULL; |
|
617 } |
|
618 Py_RETURN_NONE; |
|
619 } |
|
620 |
|
621 static void |
|
622 bytesio_dealloc(BytesIOObject *self) |
|
623 { |
|
624 if (self->buf != NULL) { |
|
625 PyMem_Free(self->buf); |
|
626 self->buf = NULL; |
|
627 } |
|
628 Py_TYPE(self)->tp_free(self); |
|
629 } |
|
630 |
|
631 static PyObject * |
|
632 bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
|
633 { |
|
634 BytesIOObject *self; |
|
635 |
|
636 assert(type != NULL && type->tp_alloc != NULL); |
|
637 self = (BytesIOObject *)type->tp_alloc(type, 0); |
|
638 if (self == NULL) |
|
639 return NULL; |
|
640 |
|
641 self->string_size = 0; |
|
642 self->pos = 0; |
|
643 self->buf_size = 0; |
|
644 self->buf = (char *)PyMem_Malloc(0); |
|
645 if (self->buf == NULL) { |
|
646 Py_DECREF(self); |
|
647 return PyErr_NoMemory(); |
|
648 } |
|
649 |
|
650 return (PyObject *)self; |
|
651 } |
|
652 |
|
653 static int |
|
654 bytesio_init(BytesIOObject *self, PyObject *args, PyObject *kwds) |
|
655 { |
|
656 PyObject *initvalue = NULL; |
|
657 |
|
658 if (!PyArg_ParseTuple(args, "|O:BytesIO", &initvalue)) |
|
659 return -1; |
|
660 |
|
661 /* In case, __init__ is called multiple times. */ |
|
662 self->string_size = 0; |
|
663 self->pos = 0; |
|
664 |
|
665 if (initvalue && initvalue != Py_None) { |
|
666 PyObject *res; |
|
667 res = bytesio_write(self, initvalue); |
|
668 if (res == NULL) |
|
669 return -1; |
|
670 Py_DECREF(res); |
|
671 self->pos = 0; |
|
672 } |
|
673 |
|
674 return 0; |
|
675 } |
|
676 |
|
677 static PyGetSetDef bytesio_getsetlist[] = { |
|
678 {"closed", (getter)bytesio_get_closed, NULL, |
|
679 "True if the file is closed."}, |
|
680 {0}, /* sentinel */ |
|
681 }; |
|
682 |
|
683 static struct PyMethodDef bytesio_methods[] = { |
|
684 {"readable", (PyCFunction)return_true, METH_NOARGS, NULL}, |
|
685 {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL}, |
|
686 {"writable", (PyCFunction)return_true, METH_NOARGS, NULL}, |
|
687 {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc}, |
|
688 {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc}, |
|
689 {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc}, |
|
690 {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc}, |
|
691 {"write", (PyCFunction)bytesio_write, METH_O, write_doc}, |
|
692 {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc}, |
|
693 {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc}, |
|
694 {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc}, |
|
695 {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc}, |
|
696 {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc}, |
|
697 {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc}, |
|
698 {"getvalue", (PyCFunction)bytesio_getvalue, METH_VARARGS, getval_doc}, |
|
699 {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc}, |
|
700 {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc}, |
|
701 {NULL, NULL} /* sentinel */ |
|
702 }; |
|
703 |
|
704 PyDoc_STRVAR(bytesio_doc, |
|
705 "BytesIO([buffer]) -> object\n" |
|
706 "\n" |
|
707 "Create a buffered I/O implementation using an in-memory bytes\n" |
|
708 "buffer, ready for reading and writing."); |
|
709 |
|
710 static PyTypeObject BytesIO_Type = { |
|
711 PyVarObject_HEAD_INIT(NULL, 0) |
|
712 "_bytesio._BytesIO", /*tp_name*/ |
|
713 sizeof(BytesIOObject), /*tp_basicsize*/ |
|
714 0, /*tp_itemsize*/ |
|
715 (destructor)bytesio_dealloc, /*tp_dealloc*/ |
|
716 0, /*tp_print*/ |
|
717 0, /*tp_getattr*/ |
|
718 0, /*tp_setattr*/ |
|
719 0, /*tp_compare*/ |
|
720 0, /*tp_repr*/ |
|
721 0, /*tp_as_number*/ |
|
722 0, /*tp_as_sequence*/ |
|
723 0, /*tp_as_mapping*/ |
|
724 0, /*tp_hash*/ |
|
725 0, /*tp_call*/ |
|
726 0, /*tp_str*/ |
|
727 0, /*tp_getattro*/ |
|
728 0, /*tp_setattro*/ |
|
729 0, /*tp_as_buffer*/ |
|
730 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ |
|
731 bytesio_doc, /*tp_doc*/ |
|
732 0, /*tp_traverse*/ |
|
733 0, /*tp_clear*/ |
|
734 0, /*tp_richcompare*/ |
|
735 0, /*tp_weaklistoffset*/ |
|
736 PyObject_SelfIter, /*tp_iter*/ |
|
737 (iternextfunc)bytesio_iternext, /*tp_iternext*/ |
|
738 bytesio_methods, /*tp_methods*/ |
|
739 0, /*tp_members*/ |
|
740 bytesio_getsetlist, /*tp_getset*/ |
|
741 0, /*tp_base*/ |
|
742 0, /*tp_dict*/ |
|
743 0, /*tp_descr_get*/ |
|
744 0, /*tp_descr_set*/ |
|
745 0, /*tp_dictoffset*/ |
|
746 (initproc)bytesio_init, /*tp_init*/ |
|
747 0, /*tp_alloc*/ |
|
748 bytesio_new, /*tp_new*/ |
|
749 }; |
|
750 |
|
751 PyMODINIT_FUNC |
|
752 init_bytesio(void) |
|
753 { |
|
754 PyObject *m; |
|
755 |
|
756 if (PyType_Ready(&BytesIO_Type) < 0) |
|
757 return; |
|
758 m = Py_InitModule("_bytesio", NULL); |
|
759 if (m == NULL) |
|
760 return; |
|
761 Py_INCREF(&BytesIO_Type); |
|
762 PyModule_AddObject(m, "_BytesIO", (PyObject *)&BytesIO_Type); |
|
763 } |