(root)/
Python-3.12.0/
Modules/
_testcapi/
buffer.c
       1  /* Test PEP 688 - Buffers */
       2  
       3  #include "parts.h"
       4  
       5  #include "structmember.h"           // PyMemberDef
       6  #include <stddef.h>                 // offsetof
       7  
       8  typedef struct {
       9      PyObject_HEAD
      10      PyObject *obj;
      11      Py_ssize_t references;
      12  } testBufObject;
      13  
      14  static PyObject *
      15  testbuf_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
      16  {
      17      PyObject *obj = PyBytes_FromString("test");
      18      if (obj == NULL) {
      19          return NULL;
      20      }
      21      testBufObject *self = (testBufObject *)type->tp_alloc(type, 0);
      22      if (self == NULL) {
      23          Py_DECREF(obj);
      24          return NULL;
      25      }
      26      self->obj = obj;
      27      self->references = 0;
      28      return (PyObject *)self;
      29  }
      30  
      31  static int
      32  testbuf_traverse(testBufObject *self, visitproc visit, void *arg)
      33  {
      34      Py_VISIT(self->obj);
      35      return 0;
      36  }
      37  
      38  static int
      39  testbuf_clear(testBufObject *self)
      40  {
      41      Py_CLEAR(self->obj);
      42      return 0;
      43  }
      44  
      45  static void
      46  testbuf_dealloc(testBufObject *self)
      47  {
      48      PyObject_GC_UnTrack(self);
      49      Py_XDECREF(self->obj);
      50      Py_TYPE(self)->tp_free((PyObject *) self);
      51  }
      52  
      53  static int
      54  testbuf_getbuf(testBufObject *self, Py_buffer *view, int flags)
      55  {
      56      int buf = PyObject_GetBuffer(self->obj, view, flags);
      57      Py_SETREF(view->obj, Py_NewRef(self));
      58      self->references++;
      59      return buf;
      60  }
      61  
      62  static void
      63  testbuf_releasebuf(testBufObject *self, Py_buffer *view)
      64  {
      65      self->references--;
      66      assert(self->references >= 0);
      67  }
      68  
      69  static PyBufferProcs testbuf_as_buffer = {
      70      .bf_getbuffer = (getbufferproc) testbuf_getbuf,
      71      .bf_releasebuffer = (releasebufferproc) testbuf_releasebuf,
      72  };
      73  
      74  static struct PyMemberDef testbuf_members[] = {
      75      {"references", T_PYSSIZET, offsetof(testBufObject, references), READONLY},
      76      {NULL},
      77  };
      78  
      79  static PyTypeObject testBufType = {
      80      PyVarObject_HEAD_INIT(NULL, 0)
      81      .tp_name = "testBufType",
      82      .tp_basicsize = sizeof(testBufObject),
      83      .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
      84      .tp_new = testbuf_new,
      85      .tp_dealloc = (destructor) testbuf_dealloc,
      86      .tp_traverse = (traverseproc) testbuf_traverse,
      87      .tp_clear = (inquiry) testbuf_clear,
      88      .tp_as_buffer = &testbuf_as_buffer,
      89      .tp_members = testbuf_members
      90  };
      91  
      92  int
      93  _PyTestCapi_Init_Buffer(PyObject *m) {
      94      if (PyType_Ready(&testBufType) < 0) {
      95          return -1;
      96      }
      97      if (PyModule_AddObjectRef(m, "testBuf", (PyObject *)&testBufType)) {
      98          return -1;
      99      }
     100  
     101      return 0;
     102  }