LCOV - code coverage report
Current view: | top level - Objects - picklebufobject.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 0 | 84 | 0.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 0 | 11 | 0.0 %
|  |  | Branches: | 0 | 32 | 0.0 %

               Branch data     Line data    Source code
           1                 :            : /* PickleBuffer object implementation */
           2                 :            :
           3                 :            : #define PY_SSIZE_T_CLEAN
           4                 :            : #include "Python.h"
           5                 :            : #include <stddef.h>
           6                 :            :
           7                 :            : typedef struct {
           8                 :            :     PyObject_HEAD
           9                 :            :     /* The view exported by the original object */
          10                 :            :     Py_buffer view;
          11                 :            :     PyObject *weakreflist;
          12                 :            : } PyPickleBufferObject;
          13                 :            :
          14                 :            : /* C API */
          15                 :            :
          16                 :            : PyObject *
          17                 :          0 : PyPickleBuffer_FromObject(PyObject *base)
          18                 :            : {
          19                 :          0 :     PyTypeObject *type = &PyPickleBuffer_Type;
          20                 :            :     PyPickleBufferObject *self;
          21                 :            :
          22                 :          0 :     self = (PyPickleBufferObject *) type->tp_alloc(type, 0);
          23         [ #  # ]:          0 :     if (self == NULL) {
          24                 :          0 :         return NULL;
          25                 :            :     }
          26                 :          0 :     self->view.obj = NULL;
          27                 :          0 :     self->weakreflist = NULL;
          28         [ #  # ]:          0 :     if (PyObject_GetBuffer(base, &self->view, PyBUF_FULL_RO) < 0) {
          29                 :          0 :         Py_DECREF(self);
          30                 :          0 :         return NULL;
          31                 :            :     }
          32                 :          0 :     return (PyObject *) self;
          33                 :            : }
          34                 :            :
          35                 :            : const Py_buffer *
          36                 :          0 : PyPickleBuffer_GetBuffer(PyObject *obj)
          37                 :            : {
          38                 :          0 :     PyPickleBufferObject *self = (PyPickleBufferObject *) obj;
          39                 :            :
          40         [ #  # ]:          0 :     if (!PyPickleBuffer_Check(obj)) {
          41                 :          0 :         PyErr_Format(PyExc_TypeError,
          42                 :            :                      "expected PickleBuffer, %.200s found",
          43                 :          0 :                      Py_TYPE(obj)->tp_name);
          44                 :          0 :         return NULL;
          45                 :            :     }
          46         [ #  # ]:          0 :     if (self->view.obj == NULL) {
          47                 :          0 :         PyErr_SetString(PyExc_ValueError,
          48                 :            :                         "operation forbidden on released PickleBuffer object");
          49                 :          0 :         return NULL;
          50                 :            :     }
          51                 :          0 :     return &self->view;
          52                 :            : }
          53                 :            :
          54                 :            : int
          55                 :          0 : PyPickleBuffer_Release(PyObject *obj)
          56                 :            : {
          57                 :          0 :     PyPickleBufferObject *self = (PyPickleBufferObject *) obj;
          58                 :            :
          59         [ #  # ]:          0 :     if (!PyPickleBuffer_Check(obj)) {
          60                 :          0 :         PyErr_Format(PyExc_TypeError,
          61                 :            :                      "expected PickleBuffer, %.200s found",
          62                 :          0 :                      Py_TYPE(obj)->tp_name);
          63                 :          0 :         return -1;
          64                 :            :     }
          65                 :          0 :     PyBuffer_Release(&self->view);
          66                 :          0 :     return 0;
          67                 :            : }
          68                 :            :
          69                 :            : static PyObject *
          70                 :          0 : picklebuf_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
          71                 :            : {
          72                 :            :     PyPickleBufferObject *self;
          73                 :            :     PyObject *base;
          74                 :          0 :     char *keywords[] = {"", NULL};
          75                 :            :
          76         [ #  # ]:          0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:PickleBuffer",
          77                 :            :                                      keywords, &base)) {
          78                 :          0 :         return NULL;
          79                 :            :     }
          80                 :            :
          81                 :          0 :     self = (PyPickleBufferObject *) type->tp_alloc(type, 0);
          82         [ #  # ]:          0 :     if (self == NULL) {
          83                 :          0 :         return NULL;
          84                 :            :     }
          85                 :          0 :     self->view.obj = NULL;
          86                 :          0 :     self->weakreflist = NULL;
          87         [ #  # ]:          0 :     if (PyObject_GetBuffer(base, &self->view, PyBUF_FULL_RO) < 0) {
          88                 :          0 :         Py_DECREF(self);
          89                 :          0 :         return NULL;
          90                 :            :     }
          91                 :          0 :     return (PyObject *) self;
          92                 :            : }
          93                 :            :
          94                 :            : static int
          95                 :          0 : picklebuf_traverse(PyPickleBufferObject *self, visitproc visit, void *arg)
          96                 :            : {
          97   [ #  #  #  # ]:          0 :     Py_VISIT(self->view.obj);
          98                 :          0 :     return 0;
          99                 :            : }
         100                 :            :
         101                 :            : static int
         102                 :          0 : picklebuf_clear(PyPickleBufferObject *self)
         103                 :            : {
         104                 :          0 :     PyBuffer_Release(&self->view);
         105                 :          0 :     return 0;
         106                 :            : }
         107                 :            :
         108                 :            : static void
         109                 :          0 : picklebuf_dealloc(PyPickleBufferObject *self)
         110                 :            : {
         111                 :          0 :     PyObject_GC_UnTrack(self);
         112         [ #  # ]:          0 :     if (self->weakreflist != NULL)
         113                 :          0 :         PyObject_ClearWeakRefs((PyObject *) self);
         114                 :          0 :     PyBuffer_Release(&self->view);
         115                 :          0 :     Py_TYPE(self)->tp_free((PyObject *) self);
         116                 :          0 : }
         117                 :            :
         118                 :            : /* Buffer API */
         119                 :            :
         120                 :            : static int
         121                 :          0 : picklebuf_getbuf(PyPickleBufferObject *self, Py_buffer *view, int flags)
         122                 :            : {
         123         [ #  # ]:          0 :     if (self->view.obj == NULL) {
         124                 :          0 :         PyErr_SetString(PyExc_ValueError,
         125                 :            :                         "operation forbidden on released PickleBuffer object");
         126                 :          0 :         return -1;
         127                 :            :     }
         128                 :          0 :     return PyObject_GetBuffer(self->view.obj, view, flags);
         129                 :            : }
         130                 :            :
         131                 :            : static void
         132                 :          0 : picklebuf_releasebuf(PyPickleBufferObject *self, Py_buffer *view)
         133                 :            : {
         134                 :            :     /* Since our bf_getbuffer redirects to the original object, this
         135                 :            :      * implementation is never called.  It only exists to signal that
         136                 :            :      * buffers exported by PickleBuffer have non-trivial releasing
         137                 :            :      * behaviour (see check in Python/getargs.c).
         138                 :            :      */
         139                 :          0 : }
         140                 :            :
         141                 :            : static PyBufferProcs picklebuf_as_buffer = {
         142                 :            :     .bf_getbuffer = (getbufferproc) picklebuf_getbuf,
         143                 :            :     .bf_releasebuffer = (releasebufferproc) picklebuf_releasebuf,
         144                 :            : };
         145                 :            :
         146                 :            : /* Methods */
         147                 :            :
         148                 :            : static PyObject *
         149                 :          0 : picklebuf_raw(PyPickleBufferObject *self, PyObject *Py_UNUSED(ignored))
         150                 :            : {
         151         [ #  # ]:          0 :     if (self->view.obj == NULL) {
         152                 :          0 :         PyErr_SetString(PyExc_ValueError,
         153                 :            :                         "operation forbidden on released PickleBuffer object");
         154                 :          0 :         return NULL;
         155                 :            :     }
         156         [ #  # ]:          0 :     if (self->view.suboffsets != NULL
         157         [ #  # ]:          0 :         || !PyBuffer_IsContiguous(&self->view, 'A')) {
         158                 :          0 :         PyErr_SetString(PyExc_BufferError,
         159                 :            :                         "cannot extract raw buffer from non-contiguous buffer");
         160                 :          0 :         return NULL;
         161                 :            :     }
         162                 :          0 :     PyObject *m = PyMemoryView_FromObject((PyObject *) self);
         163         [ #  # ]:          0 :     if (m == NULL) {
         164                 :          0 :         return NULL;
         165                 :            :     }
         166                 :          0 :     PyMemoryViewObject *mv = (PyMemoryViewObject *) m;
         167                 :            :     assert(mv->view.suboffsets == NULL);
         168                 :            :     /* Mutate memoryview instance to make it a "raw" memoryview */
         169                 :          0 :     mv->view.format = "B";
         170                 :          0 :     mv->view.ndim = 1;
         171                 :          0 :     mv->view.itemsize = 1;
         172                 :            :     /* shape = (length,) */
         173                 :          0 :     mv->view.shape = &mv->view.len;
         174                 :            :     /* strides = (1,) */
         175                 :          0 :     mv->view.strides = &mv->view.itemsize;
         176                 :            :     /* Fix memoryview state flags */
         177                 :            :     /* XXX Expose memoryobject.c's init_flags() instead? */
         178                 :          0 :     mv->flags = _Py_MEMORYVIEW_C | _Py_MEMORYVIEW_FORTRAN;
         179                 :          0 :     return m;
         180                 :            : }
         181                 :            :
         182                 :            : PyDoc_STRVAR(picklebuf_raw_doc,
         183                 :            : "raw($self, /)\n--\n\
         184                 :            : \n\
         185                 :            : Return a memoryview of the raw memory underlying this buffer.\n\
         186                 :            : Will raise BufferError is the buffer isn't contiguous.");
         187                 :            :
         188                 :            : static PyObject *
         189                 :          0 : picklebuf_release(PyPickleBufferObject *self, PyObject *Py_UNUSED(ignored))
         190                 :            : {
         191                 :          0 :     PyBuffer_Release(&self->view);
         192                 :          0 :     Py_RETURN_NONE;
         193                 :            : }
         194                 :            :
         195                 :            : PyDoc_STRVAR(picklebuf_release_doc,
         196                 :            : "release($self, /)\n--\n\
         197                 :            : \n\
         198                 :            : Release the underlying buffer exposed by the PickleBuffer object.");
         199                 :            :
         200                 :            : static PyMethodDef picklebuf_methods[] = {
         201                 :            :     {"raw",     (PyCFunction) picklebuf_raw,     METH_NOARGS, picklebuf_raw_doc},
         202                 :            :     {"release", (PyCFunction) picklebuf_release, METH_NOARGS, picklebuf_release_doc},
         203                 :            :     {NULL,      NULL}
         204                 :            : };
         205                 :            :
         206                 :            : PyTypeObject PyPickleBuffer_Type = {
         207                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
         208                 :            :     .tp_name = "pickle.PickleBuffer",
         209                 :            :     .tp_doc = PyDoc_STR("Wrapper for potentially out-of-band buffers"),
         210                 :            :     .tp_basicsize = sizeof(PyPickleBufferObject),
         211                 :            :     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
         212                 :            :     .tp_new = picklebuf_new,
         213                 :            :     .tp_dealloc = (destructor) picklebuf_dealloc,
         214                 :            :     .tp_traverse = (traverseproc) picklebuf_traverse,
         215                 :            :     .tp_clear = (inquiry) picklebuf_clear,
         216                 :            :     .tp_weaklistoffset = offsetof(PyPickleBufferObject, weakreflist),
         217                 :            :     .tp_as_buffer = &picklebuf_as_buffer,
         218                 :            :     .tp_methods = picklebuf_methods,
         219                 :            : };

Generated by: LCOV version 1.14