X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/e8a6a67b3c84fce435c3320b20d789001a158379..7f5c0c27f85afa10f7a123e4bde03534602b6619:/bytestring.c diff --git a/bytestring.c b/bytestring.c index 82d117f..ced62b4 100644 --- a/bytestring.c +++ b/bytestring.c @@ -30,14 +30,14 @@ /*----- Main code ---------------------------------------------------------*/ -PyTypeObject *bytestring_pytype; +static PyTypeObject *bytestring_pytype; static PyObject *empty, *bytev[256]; static PyObject *allocate(PyTypeObject *ty, size_t n) { - PyStringObject *x; - x = (PyStringObject *)ty->tp_alloc(ty, n); + BINOBJ *x; + x = (BINOBJ *)ty->tp_alloc(ty, n); x->ob_sval[n] = 0; #if defined(CACHE_HASH) || PY_VERSION_HEX >= 0x02030000 x->ob_shash = -1; @@ -57,13 +57,13 @@ static PyObject *dowrap(PyTypeObject *ty, const void *p, size_t n) 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; } + { bytev[ch] = allocate(ty, 1); *BIN_PTR(bytev[ch]) = ch; } Py_INCREF(bytev[ch]); return (bytev[ch]); } } x = allocate(ty, n); - if (p) memcpy(PyString_AS_STRING(x), p, n); + if (p) memcpy(BIN_PTR(x), p, n); return (x); } @@ -76,33 +76,31 @@ PyObject *bytestring_pywrapbuf(buf *b) static PyObject *bytestring_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - const char *p; - Py_ssize_t n; + struct bin in; static const char *const kwlist[] = { "data", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &p, &n)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &in)) return (0); - return (dowrap(ty, p, n)); + return (dowrap(ty, in.p, in.sz)); } static PyObject *meth_ctstreq(PyObject *me, PyObject *arg) { - char *p, *q; - Py_ssize_t psz, qsz; - if (!PyArg_ParseTuple(arg, "s#s#:ctstreq", &p, &psz, &q, &qsz)) + struct bin s0, s1; + if (!PyArg_ParseTuple(arg, "O&O&:ctstreq", convbin, &s0 , convbin, &s1)) goto end; - if (psz == qsz && ct_memeq(p, q, psz)) RETURN_TRUE; + if (s0.sz == s1.sz && ct_memeq(s0.p, s1.p, s0.sz)) RETURN_TRUE; else RETURN_FALSE; end: 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); + memset(BIN_PTR(rc), 0, sz); end: return (rc); } @@ -110,25 +108,24 @@ end: static PyObject *bytestring_pyrichcompare(PyObject *me, PyObject *you, int op) { + struct bin s0, s1; int b; - void *mystr, *yourstr; - Py_ssize_t mylen, yourlen, minlen; + Py_ssize_t minlen; - if (!PyString_Check(me) || !PyString_Check(you)) RETURN_NOTIMPL; - mystr = PyString_AS_STRING(me); mylen = PyString_GET_SIZE(me); - yourstr = PyString_AS_STRING(you); yourlen = PyString_GET_SIZE(you); + s0.p = BIN_PTR(me); s0.sz = BIN_LEN(me); + if (!convbin(you, &s1)) { PyErr_Clear(); RETURN_NOTIMPL; } switch (op) { case Py_EQ: - b = mylen == yourlen && ct_memeq(mystr, yourstr, mylen); + b = s0.sz == s1.sz && ct_memeq(s0.p, s1.p, s1.sz); break; case Py_NE: - b = mylen != yourlen || !ct_memeq(mystr, yourstr, mylen); + b = s0.sz != s1.sz || !ct_memeq(s0.p, s1.p, s1.sz); break; default: - minlen = mylen < yourlen ? mylen : yourlen; - b = memcmp(mystr, yourstr, minlen); - if (!b) b = mylen < yourlen ? -1 : mylen > yourlen ? +1 : 0; + minlen = s0.sz < s1.sz ? s0.sz : s1.sz; + b = memcmp(s0.p, s1.p, minlen); + if (!b) b = s0.sz < s1.sz ? -1 : s0.sz > s1.sz ? +1 : 0; switch (op) { case Py_LT: b = b < 0; break; case Py_LE: b = b <= 0; break; @@ -143,17 +140,14 @@ static PyObject *bytestring_pyrichcompare(PyObject *me, static PyObject *bytestring_pyconcat(PyObject *x, PyObject *y) { - const void *xv; Py_ssize_t xsz; - const void *yv; Py_ssize_t ysz; + struct bin xx, yy; 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); + if (!convbin(x, &xx) || !convbin(y, &yy)) goto end; + zsz = (size_t)xx.sz + (size_t)yy.sz; + if (xx.sz < 0 || yy.sz < 0 || zsz < xx.sz) VALERR("too long"); + z = bytestring_pywrap(0, zsz); zp = BIN_PTR(z); + memcpy(zp, xx.p, xx.sz); memcpy(zp + xx.sz, yy.p, yy.sz); end: return (z); } @@ -163,10 +157,10 @@ 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); + xp = (const unsigned char *)BIN_PTR(me); + xsz = BIN_LEN(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); + zsz = n*xsz; z = bytestring_pywrap(0, zsz); zp = BIN_PTR(z); if (xsz == 1) memset(zp, *xp, zsz); else while (zsz) { memcpy(zp, xp, xsz); zp += xsz; zsz -= xsz; } end: @@ -177,8 +171,8 @@ 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); + if (i < 0 || i >= BIN_LEN(me)) IXERR("out of range"); + rc = bytestring_pywrap(BIN_PTR(me) + i, 1); end: return (rc); } @@ -186,15 +180,15 @@ end: static PyObject *bytestring_pyslice(PyObject *me, Py_ssize_t i, Py_ssize_t j) { PyObject *rc = 0; - size_t n = PyString_GET_SIZE(me); + size_t n = BIN_LEN(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) + if (i == 0 && j == n && Py_TYPE(me) == bytestring_pytype) { Py_INCREF(me); rc = me; goto end; } - rc = bytestring_pywrap(PyString_AS_STRING(me) + i, j - i); + rc = bytestring_pywrap(BIN_PTR(me) + i, j - i); end: return (rc); } @@ -209,16 +203,16 @@ static PyObject *bytestring_pysubscript(PyObject *me, PyObject *ix) 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); + if (i < 0) i += BIN_LEN(me); rc = bytestring_pyitem(me, i); } else if (PySlice_Check(ix)) { - if (PySlice_GetIndicesEx((PySliceObject *)ix, PyString_GET_SIZE(me), + if (PySlice_GetIndicesEx((PySliceObject *)ix, BIN_LEN(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); + p = (unsigned char *)BIN_PTR(me) + i; + q = (unsigned char *)BIN_PTR(rc); while (n--) { *q++ = *p; p += k; } } else TYERR("wanted integer or slice"); @@ -228,19 +222,16 @@ end: #define BINOP(name, op) \ static PyObject *bytestring_py##name(PyObject *x, PyObject *y) { \ - const void *xv, *yv; \ + struct bin xx, yy; \ const unsigned char *xp, *yp; \ unsigned char *zp; \ - Py_ssize_t xsz, ysz; \ int i; \ PyObject *rc = 0; \ - if (PyObject_AsReadBuffer(x, &xv, &xsz) || \ - PyObject_AsReadBuffer(y, &yv, &ysz)) \ - goto end; \ - if (xsz != ysz) VALERR("length mismatch"); \ - rc = bytestring_pywrap(0, xsz); \ - xp = xv; yp = yv; zp = (unsigned char *)PyString_AS_STRING(rc); \ - for (i = xsz; i > 0; i--) *zp++ = *xp++ op *yp++; \ + if (!convbin(x, &xx) || !convbin(y, &yy)) goto end; \ + if (xx.sz != yy.sz) VALERR("length mismatch"); \ + rc = bytestring_pywrap(0, xx.sz); \ + xp = xx.p; yp = yy.p; zp = (unsigned char *)BIN_PTR(rc); \ + for (i = xx.sz; i > 0; i--) *zp++ = *xp++ op *yp++; \ end: \ return (rc); \ } @@ -250,22 +241,28 @@ BINOP(xor, ^) #define UNOP(name, op) \ static PyObject *bytestring_py##name(PyObject *x) { \ - const void *xv; \ + struct bin xx; \ const unsigned char *xp; \ unsigned char *zp; \ - Py_ssize_t xsz; \ int i; \ PyObject *rc = 0; \ - if (PyObject_AsReadBuffer(x, &xv, &xsz)) goto end; \ - rc = bytestring_pywrap(0, xsz); \ - xp = xv; zp = (unsigned char *)PyString_AS_STRING(rc); \ - for (i = xsz; i > 0; i--) *zp++ = op *xp++; \ + if (!convbin(x, &xx)) goto end; \ + rc = bytestring_pywrap(0, xx.sz); \ + xp = xx.p; zp = (unsigned char *)BIN_PTR(rc); \ + for (i = xx.sz; i > 0; i--) *zp++ = op *xp++; \ end: \ return (rc); \ } 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@ */ @@ -291,7 +288,7 @@ static PyNumberMethods bytestring_pynumber = { 0, /* @nb_hex@ */ }; -static PySequenceMethods bytestring_pysequence = { +static const PySequenceMethods bytestring_pysequence = { 0, /* @sq_length@ */ bytestring_pyconcat, /* @sq_concat@ */ bytestring_pyrepeat, /* @sq_repeat@ */ @@ -304,16 +301,14 @@ static PySequenceMethods bytestring_pysequence = { 0, /* @sq_inplace_repeat@ */ }; -static PyMappingMethods bytestring_pymapping = { +static const PyMappingMethods bytestring_pymapping = { 0, /* @mp_length@ */ bytestring_pysubscript, /* @mp_subscript@ */ 0, /* @mp_ass_subscript@ */ }; -static PyBufferProcs bytestring_pybuffer; - -static PyTypeObject bytestring_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject bytestring_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ByteString", /* @tp_name@ */ 0, /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -324,21 +319,21 @@ static PyTypeObject bytestring_pytype_skel = { 0, /* @tp_setattr@ */ 0, /* @tp_compare@ */ 0, /* @tp_repr@ */ - &bytestring_pynumber, /* @tp_as_number@ */ - &bytestring_pysequence, /* @tp_as_sequence@ */ - &bytestring_pymapping, /* @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@ */ @@ -346,7 +341,7 @@ static PyTypeObject bytestring_pytype_skel = { 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@ */ @@ -363,15 +358,14 @@ static PyTypeObject bytestring_pytype_skel = { /*----- 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 } }; -#define string_pytype &PyString_Type +#define string_pytype &BIN_TYPE void bytestring_pyinit(void) { INITTYPE(bytestring, string);