The Buffer type contains a fixed length character array. Array subscripting works with a string of size one. Slicing works on strings and buffers, returning a new buffer of the size of the slice.staticforward PyTypeObject MyBuffer_Type; typedef struct { PyObject_HEAD int size; char *p; } Buffer; #define Buffer_Check(v) ((PyObject *)(v)->ob_type == &MyBuffer_Type) #define Buffer_size(v) ((Buffer *)(v)->size) #define Buffer_data(v) ((Buffer *)(v)->p)
Define a variable of type PySequenceMethods
and include a
pointer to it in the tp_as_sequence
slot in the
PyTypeObject
definition of a new type.
For deletion of items, the object passed to functions in the sq_ass_item and sq_ass_slice slots isPySequenceMethods counter_as_sequence = { Buffer_Len, /* inquiry sq_length; /* __len__ */ Buffer_Concat, /* binaryfunc sq_concat; /* __add__ */ Buffer_Repeat, /* intargfunc sq_repeat; /* __mul__ */ Buffer_GetItem, /* intargfunc sq_item; /* __getitem__ */ Buffer_GetSlice, /* intintargfunc sq_slice; /* __getslice__ */ Buffer_SetItem, /* intobjargproc sq_ass_item; /* __setitem__ */ Buffer_SetSlice, /* intintobjargproc sq_ass_slice; /* __setslice__ */ };
NULL
.
If a slot does not contain a function, replace it with 0.
The length in this example is fixed, but could be determined at runtime.
int Buffer_Len(self) PyObject *self; { return Buffer_size(self); }
The index passed is an integer which may be negative or positive. If the index is out-of-bounds, then adjust to the closest boundary.
If the passed value isPyObject * Buffer_GetItem(self, index) PyObject *self; int index; { PyObject *result = NULL; int n = Buffer_size(self); if (index < 0) index += n; if (0 <= index < n) result = PyString_FromStringAndSize(Buffer_data(self)[i], 1); else PyErr_SetString(PyExc_IndexError, "buffer index out of range"); return result; } int Buffer_SetItem(self, index, value) PyObject *self, *value; int index; { int n = Buffer_size(self); char *c; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "object doesn't support item deletion"); return -1; } else if (!PyString_Check(value)) { PyErr_SetString(PyExc_TypeError, "expecting string"); return -1; } if (index < 0) index += n; if (0 <= index < n) { c = PyString_AsString(value); Buffer_data(self)[index] = *c; /* just one character */ return 0; } else { PyErr_SetString(PyExc_IndexError, "buffer index out of range"); return -1; } }
NULL
for the setitem function, then
delete the item from the sequence.
The indices passed are integers which may be negative or positive. If an index is out-of-bounds, then adjust to the closest boundary. If the lower index is greater than the higher index, return an empty sequence. Where int is the return type, return is -1 on error or 0 on success.
If the passed value isint Buffer_SetSlice(self, ilow, ihigh, value) PyObject *self, *value; int ilow, ihigh; { int i, n, l; char *p, *q; p = Buffer_data(self); n = Buffer_size(self); if (value == NULL) { PyErr_SetString(PyExc_TypeError, "object doesn't support item deletion"); return -1; } else if (PyString_Check(value)) { q = PyString_AsString(value); l = PyString_Size(value); } else if (Buffer_Check(value)) { q = Buffer_data(value); l = Buffer_size(value); } else { PyErr_SetString(PyExc_TypeError, "expecting string or buffer"); return -1; } if (ilow < 0) ilow += n; if (ihigh < 0) ihigh += n; if (ilow >= n) ilow = n-1; if (ihigh > n) ihigh = n; if (ihigh - ilow > l) { PyErr_SetString(PyExc_ValueError, "string must be at least size of slice"); return -1; } if (0 <= ilow < ihigh < n) for (i = ilow; i < ihigh; i++) p[i] = *q++; return 0; } PyObject * Buffer_GetSlice(self, ilow, ihigh) PyObject *self; int ilow, ihigh; { PyObject *temp, *result = NULL; int n = Buffer_size(self); if (ilow < 0) ilow += n; if (ihigh < 0) ihigh += n; if (ilow >= n) ilow = n-1; if (ihigh > n) ihigh = n; if (0 <= ilow < ihigh < n) { temp = PyString_FromStringAndSize(Buffer_data(self)+ilow, ihigh-ilow); result = Buffer_NEW(ihigh-ilow); if (Buffer_SetSlice(result, 0, ihigh-ilow, temp) != -1) { Py_DECREF(result); return (PyObject *)NULL; } } else { result = Buffer_NEW(0); } return result; }
NULL
for the setslice function
then delete the elements in the slice.
PyObject * Buffer_Concat(self, other) PyObject *self, *other; { PyObject *result = NULL; int sl, ol; sl = Buffer_size(self); if (Buffer_Check(other)) { ol = Buffer_size(other); } else if (PyString_Check(other)) { ol = PyString_Size(other); } else { PyErr_SetString(PyExc_TypeError, "expecting string"); return result; } result = Buffer_NEW(sl+ol); if (Buffer_SetSlice(result, 0, sl, self) == -1 || Buffer_SetSlice(result, sl, sl+ol, other) == -1) { Py_DECREF(result); return (PyObject *)NULL; } return result; } PyObject * Buffer_Repeat(self, count) PyObject *self; int count; { PyObject *result = NULL; int p, n = Buffer_size(self); if (count < 0) { result = Buffer_NEW(0); } else { result = Buffer_NEW(n * count); if (result != NULL) for (p = 0; count>=0; count--, p+=n) if (Buffer_SetSlice(result, p, p+n, other) == -1) { Py_DECREF(result); return (PyObject *)NULL; } } return result; }
append
count
extend
index
insert
pop
remove
reverse
sort