From b5ddcfd2a203336f3ba7bb1111cda462333c9e1f Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 11 Apr 2007 17:08:28 +0000 Subject: [PATCH] Make array().tofile() work with a new I/O object. --- Lib/test/test_array.py | 2 +- Modules/arraymodule.c | 34 +++++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 692760ce906..ae7156b44aa 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -147,7 +147,7 @@ class BaseTest(unittest.TestCase): def test_tofromfile(self): a = array.array(self.typecode, 2*self.example) self.assertRaises(TypeError, a.tofile) - self.assertRaises(TypeError, a.tofile, cStringIO.StringIO()) + ##self.assertRaises(TypeError, a.tofile, cStringIO.StringIO()) f = open(test_support.TESTFN, 'wb') try: a.tofile(f) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 3d8674c985b..7fe0b26e89e 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1252,12 +1252,11 @@ array_tofile(arrayobject *self, PyObject *f) { FILE *fp; + if (self->ob_size == 0) + goto done; + fp = PyFile_AsFile(f); - if (fp == NULL) { - PyErr_SetString(PyExc_TypeError, "arg must be open file"); - return NULL; - } - if (self->ob_size > 0) { + if (fp != NULL) { if (fwrite(self->ob_item, self->ob_descr->itemsize, self->ob_size, fp) != (size_t)self->ob_size) { PyErr_SetFromErrno(PyExc_IOError); @@ -1265,6 +1264,31 @@ array_tofile(arrayobject *self, PyObject *f) return NULL; } } + else { + Py_ssize_t nbytes = self->ob_size * self->ob_descr->itemsize; + /* Write 64K blocks at a time */ + /* XXX Make the block size settable */ + int BLOCKSIZE = 64*1024; + Py_ssize_t nblocks = (nbytes + BLOCKSIZE - 1) / BLOCKSIZE; + Py_ssize_t i; + for (i = 0; i < nblocks; i++) { + char* ptr = self->ob_item + i*BLOCKSIZE; + Py_ssize_t size = BLOCKSIZE; + PyObject *bytes, *res; + if (i*BLOCKSIZE + size > nbytes) + size = nbytes - i*BLOCKSIZE; + bytes = PyBytes_FromStringAndSize(ptr, size); + if (bytes == NULL) + return NULL; + res = PyObject_CallMethod(f, "write", "O", + bytes); + Py_DECREF(bytes); + if (res == NULL) + return NULL; + } + } + + done: Py_INCREF(Py_None); return Py_None; }