/*----- Main code ---------------------------------------------------------*/
-PyTypeObject *bytestring_pytype;
+static PyTypeObject *bytestring_pytype;
+
+static PyObject *empty, *bytev[256];
static PyObject *allocate(PyTypeObject *ty, size_t n)
{
static PyObject *dowrap(PyTypeObject *ty, const void *p, size_t n)
{
PyObject *x;
+ int ch;
+
+ if (p && ty == bytestring_pytype) {
+ if (!n) {
+ if (!empty) empty = allocate(ty, 0);
+ Py_INCREF(empty); return (empty);
+ } else if (n == 1 && (ch = *(unsigned char *)p) < sizeof(bytev)) {
+ if (!bytev[ch])
+ { bytev[ch] = allocate(ty, 1); *PyString_AS_STRING(bytev[ch]) = ch; }
+ Py_INCREF(bytev[ch]); return (bytev[ch]);
+ }
+ }
x = allocate(ty, n);
if (p) memcpy(PyString_AS_STRING(x), p, n);
return (0);
}
-static PyObject *meth__ByteString_zero(PyObject *me, PyObject *arg)
+static PyObject *bymeth_zero(PyObject *me, PyObject *arg)
{
size_t sz;
PyObject *rc = 0;
- if (!PyArg_ParseTuple(arg, "OO&:zero", &me, convszt, &sz)) goto end;
+ if (!PyArg_ParseTuple(arg, "O&:zero", convszt, &sz)) goto end;
rc = bytestring_pywrap(0, sz);
memset(PyString_AS_STRING(rc), 0, sz);
end:
else RETURN_FALSE;
}
+static PyObject *bytestring_pyconcat(PyObject *x, PyObject *y)
+{
+ const void *xv; Py_ssize_t xsz;
+ const void *yv; Py_ssize_t ysz;
+ PyObject *z = 0; char *zp; size_t zsz;
+
+ if (PyObject_AsReadBuffer(x, &xv, &xsz) ||
+ PyObject_AsReadBuffer(y, &yv, &ysz))
+ goto end;
+ zsz = (size_t)xsz + (size_t)ysz;
+ if (xsz < 0 || ysz < 0 || zsz < xsz) VALERR("too long");
+ z = bytestring_pywrap(0, zsz); zp = PyString_AS_STRING(z);
+ memcpy(zp, xv, xsz); memcpy(zp + xsz, yv, ysz);
+end:
+ return (z);
+}
+
+static PyObject *bytestring_pyrepeat(PyObject *me, Py_ssize_t n)
+{
+ const unsigned char *xp; size_t xsz;
+ PyObject *z = 0; char *zp; size_t zsz;
+
+ xp = (const unsigned char *)PyString_AS_STRING(me);
+ xsz = PyString_GET_SIZE(me);
+ if (n < 0 || (n && xsz >= (size_t)-1/n)) VALERR("too long");
+ zsz = n*xsz; z = bytestring_pywrap(0, zsz); zp = PyString_AS_STRING(z);
+ if (xsz == 1) memset(zp, *xp, zsz);
+ else while (zsz) { memcpy(zp, xp, xsz); zp += xsz; zsz -= xsz; }
+end:
+ return (z);
+}
+
+static PyObject *bytestring_pyitem(PyObject *me, Py_ssize_t i)
+{
+ PyObject *rc = 0;
+
+ if (i < 0 || i >= PyString_GET_SIZE(me)) IXERR("out of range");
+ rc = bytestring_pywrap(PyString_AS_STRING(me) + i, 1);
+end:
+ return (rc);
+}
+
+static PyObject *bytestring_pyslice(PyObject *me, Py_ssize_t i, Py_ssize_t j)
+{
+ PyObject *rc = 0;
+ size_t n = PyString_GET_SIZE(me);
+
+ if (i < 0) i = 0;
+ if (j < 0) j = 0;
+ else if (j > n) j = n;
+ if (j < i) i = j = 0;
+ if (i == 0 && j == n && me->ob_type == bytestring_pytype)
+ { Py_INCREF(me); rc = me; goto end; }
+ rc = bytestring_pywrap(PyString_AS_STRING(me) + i, j - i);
+end:
+ return (rc);
+}
+
+static PyObject *bytestring_pysubscript(PyObject *me, PyObject *ix)
+{
+ Py_ssize_t i, j, k, n;
+ const unsigned char *p;
+ unsigned char *q;
+ PyObject *rc = 0;
+
+ if (PyIndex_Check(ix)) {
+ i = PyNumber_AsSsize_t(ix, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred()) return (0);
+ if (i < 0) i += PyString_GET_SIZE(me);
+ rc = bytestring_pyitem(me, i);
+ } else if (PySlice_Check(ix)) {
+ if (PySlice_GetIndicesEx((PySliceObject *)ix, PyString_GET_SIZE(me),
+ &i, &j, &k, &n))
+ return (0);
+ if (k == 1) return bytestring_pyslice(me, i, j);
+ rc = bytestring_pywrap(0, n);
+ p = (unsigned char *)PyString_AS_STRING(me) + i;
+ q = (unsigned char *)PyString_AS_STRING(rc);
+ while (n--) { *q++ = *p; p += k; }
+ } else
+ TYERR("wanted integer or slice");
+end:
+ return (rc);
+}
+
#define BINOP(name, op) \
static PyObject *bytestring_py##name(PyObject *x, PyObject *y) { \
const void *xv, *yv; \
}
UNOP(not, ~)
-static PyNumberMethods bytestring_pynumber = {
+static const PyMethodDef bytestring_pymethods[] = {
+#define METHNAME(name) bymeth_##name
+ SMTH (zero, "zero(N) -> 0000...00")
+#undef METHNAME
+ { 0 }
+};
+
+static const PyNumberMethods bytestring_pynumber = {
0, /* @nb_add@ */
0, /* @nb_subtract@ */
0, /* @nb_multiply@ */
0, /* @nb_hex@ */
};
-static PyBufferProcs bytestring_pybuffer;
+static const PySequenceMethods bytestring_pysequence = {
+ 0, /* @sq_length@ */
+ bytestring_pyconcat, /* @sq_concat@ */
+ bytestring_pyrepeat, /* @sq_repeat@ */
+ bytestring_pyitem, /* @sq_item@ */
+ bytestring_pyslice, /* @sq_slice@ */
+ 0, /* @sq_ass_item@ */
+ 0, /* @sq_ass_slice@ */
+ 0, /* @sq_contains@ */
+ 0, /* @sq_inplace_concat@ */
+ 0, /* @sq_inplace_repeat@ */
+};
+
+static const PyMappingMethods bytestring_pymapping = {
+ 0, /* @mp_length@ */
+ bytestring_pysubscript, /* @mp_subscript@ */
+ 0, /* @mp_ass_subscript@ */
+};
-static PyTypeObject bytestring_pytype_skel = {
+static const PyTypeObject bytestring_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
"ByteString", /* @tp_name@ */
0, /* @tp_basicsize@ */
0, /* @tp_setattr@ */
0, /* @tp_compare@ */
0, /* @tp_repr@ */
- &bytestring_pynumber, /* @tp_as_number@ */
- 0, /* @tp_as_sequence@ */
- 0, /* @tp_as_mapping@ */
+ PYNUMBER(bytestring), /* @tp_as_number@ */
+ PYSEQUENCE(bytestring), /* @tp_as_sequence@ */
+ PYMAPPING(bytestring), /* @tp_as_mapping@ */
0, /* @tp_hash@ */
0, /* @tp_call@ */
0, /* @tp_str@ */
0, /* @tp_getattro@ */
0, /* @tp_setattro@ */
- &bytestring_pybuffer, /* @tp_as_buffer@ */
+ 0, /* @tp_as_buffer@ */
Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"ByteString(STR): byte string class.",
+ "ByteString(STR): byte string class.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
0, /* @tp_iternext@ */
- 0, /* @tp_methods@ */
+ PYMETHODS(bytestring), /* @tp_methods@ */
0, /* @tp_members@ */
0, /* @tp_getset@ */
0, /* @tp_base@ */
/*----- Initialization ----------------------------------------------------*/
-static PyMethodDef methods[] = {
+static const PyMethodDef methods[] = {
#define METHNAME(func) meth_##func
- METH (ctstreq, "ctstreq(S, T) -> BOOL")
- METH (_ByteString_zero, "zero(N) -> 0000...00")
+ METH (ctstreq, "ctstreq(S, T) -> BOOL")
#undef METHNAME
{ 0 }
};