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)
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.
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.
PySequenceMethods 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__ */
};
For deletion of items, the object passed to functions in the
sq_ass_item and sq_ass_slice slots is 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.
PyObject *
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;
}
}
If the passed value is 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.
int
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;
}
If the passed value is 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