]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Checkin of Jack's buffer mods.
authorGuido van Rossum <guido@python.org>
Mon, 5 May 1997 22:15:02 +0000 (22:15 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 5 May 1997 22:15:02 +0000 (22:15 +0000)
Not really checked, but didn't fail any tests either...

Include/object.h
Modules/arraymodule.c
Objects/fileobject.c
Objects/stringobject.c
Python/getargs.c

index 54b5481d493f91c98c466d6deaa5a6b060cefc4c..45bb41ef717b42fe27ff863592a27804fef2f08d 100644 (file)
@@ -146,6 +146,9 @@ typedef PyObject *(*intintargfunc) Py_PROTO((PyObject *, int, int));
 typedef int(*intobjargproc) Py_PROTO((PyObject *, int, PyObject *));
 typedef int(*intintobjargproc) Py_PROTO((PyObject *, int, int, PyObject *));
 typedef int(*objobjargproc) Py_PROTO((PyObject *, PyObject *, PyObject *));
+typedef int (*getreadbufferproc) Py_PROTO((PyObject *, int, void **));
+typedef int (*getwritebufferproc) Py_PROTO((PyObject *, int, void **));
+typedef int (*getsegcountproc) Py_PROTO((PyObject *, int *));
 
 typedef struct {
        binaryfunc nb_add;
@@ -189,6 +192,13 @@ typedef struct {
        objobjargproc mp_ass_subscript;
 } PyMappingMethods;
 
+typedef struct {
+       getreadbufferproc bf_getreadbuffer;
+       getwritebufferproc bf_getwritebuffer;
+       getsegcountproc bf_getsegcount;
+} PyBufferProcs;
+       
+
 typedef void (*destructor) Py_PROTO((PyObject *));
 typedef int (*printfunc) Py_PROTO((PyObject *, FILE *, int));
 typedef PyObject *(*getattrfunc) Py_PROTO((PyObject *, char *));
@@ -227,8 +237,10 @@ typedef struct _typeobject {
        getattrofunc tp_getattro;
        setattrofunc tp_setattro;
 
+       /* Functions to access object as input/output buffer */
+       PyBufferProcs *tp_as_buffer;
+       
        /* Space for future expansion */
-       long tp_xxx3;
        long tp_xxx4;
 
        char *tp_doc; /* Documentation string */
index e732f394686a1bfa72d007290d25f71cd961f2a8..50cadd01b53c3c1f70b13e888c8ae67d50bf9098 100644 (file)
@@ -1169,6 +1169,44 @@ array_repr(a)
        return s;
 }
 
+static int
+array_buffer_getreadbuf(self, index, ptr)
+       arrayobject *self;
+       int index;
+       const void **ptr;
+{
+       if ( index != 0 ) {
+               PyErr_SetString(PyExc_SystemError, "Accessing non-existent array segment");
+               return -1;
+       }
+       *ptr = (void *)self->ob_item;
+       return self->ob_size*self->ob_descr->itemsize;
+}
+
+static int
+array_buffer_getwritebuf(self, index, ptr)
+       arrayobject *self;
+       int index;
+       const void **ptr;
+{
+       if ( index != 0 ) {
+               PyErr_SetString(PyExc_SystemError, "Accessing non-existent array segment");
+               return -1;
+       }
+       *ptr = (void *)self->ob_item;
+       return self->ob_size*self->ob_descr->itemsize;
+}
+
+static int
+array_buffer_getsegcount(self, lenp)
+       arrayobject *self;
+       int *lenp;
+{
+       if ( lenp )
+               *lenp = self->ob_size*self->ob_descr->itemsize;
+       return 1;
+}
+
 static PySequenceMethods array_as_sequence = {
        (inquiry)array_length,                  /*sq_length*/
        (binaryfunc)array_concat,               /*sq_concat*/
@@ -1179,6 +1217,13 @@ static PySequenceMethods array_as_sequence = {
        (intintobjargproc)array_ass_slice,      /*sq_ass_slice*/
 };
 
+static PyBufferProcs array_as_buffer = {
+       (getreadbufferproc)array_buffer_getreadbuf,
+       (getwritebufferproc)array_buffer_getwritebuf,
+       (getsegcountproc)array_buffer_getsegcount,
+};
+
+
 statichere PyTypeObject Arraytype = {
        PyObject_HEAD_INIT(&PyType_Type)
        0,
@@ -1194,6 +1239,14 @@ statichere PyTypeObject Arraytype = {
        0,                              /*tp_as_number*/
        &array_as_sequence,             /*tp_as_sequence*/
        0,                              /*tp_as_mapping*/
+       0,                              /*tp_hash*/
+       0,                              /*tp_call*/
+       0,                              /*tp_str*/
+       0,                              /*tp_getattro*/
+       0,                              /*tp_setattro*/
+       &array_as_buffer,               /*tp_as_buffer*/
+       0,                              /*tp_xxx4*/
+       0,                              /*tp_doc*/
 };
 
 
index cee41a10e0c2bd5d38495f82faf50053c4d4f705..a4b1d4baa6eda9b12048e5db8a1e2cfe32f94ca7 100644 (file)
@@ -419,6 +419,41 @@ file_read(f, args)
        return v;
 }
 
+static PyObject *
+file_readinto(f, args)
+       PyFileObject *f;
+       PyObject *args;
+{
+       char *ptr;
+       int ntodo, ndone, nnow;
+       
+       if (f->f_fp == NULL)
+               return err_closed();
+       if (!PyArg_Parse(args, "w#", &ptr, &ntodo))
+               return NULL;
+       ndone = 0;
+       /* 
+       ** XXXX Is this correct? Other threads may see partially-completed
+       ** reads if they look at the object we're reading into...
+       */
+       Py_BEGIN_ALLOW_THREADS
+       while(ntodo > 0) {
+               nnow = fread(ptr+ndone, 1, ntodo, f->f_fp);
+               if (nnow < 0 ) {
+                       PyErr_SetFromErrno(PyExc_IOError);
+                       clearerr(f->f_fp);
+                       return NULL;
+               }
+               if (nnow == 0)
+                       break;
+               ndone += nnow;
+               ntodo -= nnow;
+       }
+       Py_END_ALLOW_THREADS
+       return PyInt_FromLong(ndone);
+}
+
+
 /* Internal routine to get a line.
    Size argument interpretation:
    > 0: max length;
@@ -688,6 +723,7 @@ static PyMethodDef file_methods[] = {
        {"tell",        (PyCFunction)file_tell, 0},
        {"write",       (PyCFunction)file_write, 0},
        {"writelines",  (PyCFunction)file_writelines, 0},
+       {"readinto",    (PyCFunction)file_readinto, 0},
        {NULL,          NULL}           /* sentinel */
 };
 
index 1f95aa1c98db2076811b0c0bd2e9d2d7e5001553..dbcb1a9969bdbc93f51d39a3fbdb0a6741de5d82 100644 (file)
@@ -456,6 +456,40 @@ string_hash(a)
        return x;
 }
 
+static int
+string_buffer_getreadbuf(self, index, ptr)
+       PyStringObject *self;
+       int index;
+       const void **ptr;
+{
+       if ( index != 0 ) {
+               PyErr_SetString(PyExc_SystemError, "Accessing non-existent string segment");
+               return -1;
+       }
+       *ptr = (void *)self->ob_sval;
+       return self->ob_size;
+}
+
+static int
+string_buffer_getwritebuf(self, index, ptr)
+       PyStringObject *self;
+       int index;
+       const void **ptr;
+{
+       PyErr_SetString(PyExc_TypeError, "Cannot use string as modifyable buffer");
+       return -1;
+}
+
+static int
+string_buffer_getsegcount(self, lenp)
+       PyStringObject *self;
+       int *lenp;
+{
+       if ( lenp )
+               *lenp = self->ob_size;
+       return 1;
+}
+
 static PySequenceMethods string_as_sequence = {
        (inquiry)string_length, /*sq_length*/
        (binaryfunc)string_concat, /*sq_concat*/
@@ -466,6 +500,12 @@ static PySequenceMethods string_as_sequence = {
        0,              /*sq_ass_slice*/
 };
 
+static PyBufferProcs string_as_buffer = {
+       (getreadbufferproc)string_buffer_getreadbuf,
+       (getwritebufferproc)string_buffer_getwritebuf,
+       (getsegcountproc)string_buffer_getsegcount,
+};
+
 PyTypeObject PyString_Type = {
        PyObject_HEAD_INIT(&PyType_Type)
        0,
@@ -486,7 +526,7 @@ PyTypeObject PyString_Type = {
        0,              /*tp_str*/
        0,              /*tp_getattro*/
        0,              /*tp_setattro*/
-       0,              /*tp_xxx3*/
+       &string_as_buffer,      /*tp_as_buffer*/
        0,              /*tp_xxx4*/
        0,              /*tp_doc*/
 };
index a2555ce5427376ac657b982c02289c57a760162b..f166921cbf12e7a3ce274dfe5aeb73d7ceb008f4 100644 (file)
@@ -539,41 +539,81 @@ convertsimple1(arg, p_format, p_va)
        
        case 's': /* string */
                {
-                       char **p = va_arg(*p_va, char **);
-                       if (PyString_Check(arg))
-                               *p = PyString_AsString(arg);
-                       else
-                               return "string";
-                       if (*format == '#') {
+                       if (*format == '#') { /* any buffer-like object */
+                               void **p = (void **)va_arg(*p_va, char **);
+                               PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
                                int *q = va_arg(*p_va, int *);
-                               *q = PyString_Size(arg);
+                               int count;
+
+                               if ( pb == NULL ||
+                                    pb->bf_getreadbuffer == NULL ||
+                                    pb->bf_getsegcount == NULL )
+                                 return "read-only buffer";
+                               if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
+                                 return "single-segment read-only buffer";
+                               if ( (count =
+                                     (*pb->bf_getreadbuffer)(arg, 0, p)) < 0 )
+                                 return "(unspecified)";
+                               *q = count;
                                format++;
+                       } else {
+                               char **p = va_arg(*p_va, char **);
+                       
+                               if (PyString_Check(arg))
+                                 *p = PyString_AsString(arg);
+                               else
+                                 return "string";
+                               if ((int)strlen(*p) != PyString_Size(arg))
+                                 return "string without null bytes";
                        }
-                       else if ((int)strlen(*p) != PyString_Size(arg))
-                               return "string without null bytes";
                        break;
                }
-       
+
        case 'z': /* string, may be NULL (None) */
                {
-                       char **p = va_arg(*p_va, char **);
-                       if (arg == Py_None)
-                               *p = 0;
-                       else if (PyString_Check(arg))
-                               *p = PyString_AsString(arg);
-                       else
-                               return "None or string";
-                       if (*format == '#') {
+                       if (*format == '#') { /* any buffer-like object */
+                               void **p = (void **)va_arg(*p_va, char **);
+                               PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
                                int *q = va_arg(*p_va, int *);
-                               if (arg == Py_None)
-                                       *q = 0;
-                               else
-                                       *q = PyString_Size(arg);
+                               int count;
+
+                               if (arg == Py_None) {
+                                 *p = 0;
+                                 *q = 0;
+                               } else {
+                                 if ( pb == NULL ||
+                                      pb->bf_getreadbuffer == NULL ||
+                                      pb->bf_getsegcount == NULL )
+                                   return "read-only buffer";
+                                 if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
+                                 return "single-segment read-only buffer";
+                                 if ( (count = (*pb->bf_getreadbuffer)
+                                                           (arg, 0, p)) < 0 )
+                                   return "(unspecified)";
+                                 *q = count;
+                               }
                                format++;
+                       } else {
+                               char **p = va_arg(*p_va, char **);
+                       
+                               if (arg == Py_None)
+                                 *p = 0;
+                               else if (PyString_Check(arg))
+                                 *p = PyString_AsString(arg);
+                               else
+                                 return "None or string";
+                               if (*format == '#') {
+                                 int *q = va_arg(*p_va, int *);
+                                 if (arg == Py_None)
+                                   *q = 0;
+                                 else
+                                   *q = PyString_Size(arg);
+                                 format++;
+                               }
+                               else if (*p != NULL &&
+                                        (int)strlen(*p) != PyString_Size(arg))
+                                 return "None or string without null bytes";
                        }
-                       else if (*p != NULL &&
-                                (int)strlen(*p) != PyString_Size(arg))
-                               return "None or string without null bytes";
                        break;
                }
        
@@ -624,6 +664,30 @@ convertsimple1(arg, p_format, p_va)
                        }
                        break;
                }
+               
+               
+       case 'w': /* memory buffer, read-write access */
+               {
+                       void **p = va_arg(*p_va, void **);
+                       PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
+                       int count;
+                       
+                       if ( pb == NULL || pb->bf_getwritebuffer == NULL ||
+                                       pb->bf_getsegcount == NULL )
+                               return "read-write buffer";
+                       if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
+                               return "single-segment read-write buffer";
+                       if ( (count = pb->bf_getwritebuffer(arg, 0, p)) < 0 )
+                               return "(unspecified)";
+                       if (*format == '#') {
+                               int *q = va_arg(*p_va, int *);
+                               
+                               *q = count;
+                               format++;
+                       }
+                       break;
+               }
+               
        
        default:
                return "impossible<bad format char>";