chiark / gitweb /
Merge remote-tracking branch 'origin/HEAD'
[catacomb-python] / bytestring.c
index 6b45d24723ac13c0029522519b3555b643749108..2b74648d91d9ca2793f206ba4091e941123465f1 100644 (file)
@@ -37,7 +37,7 @@ static PyObject *dowrap(PyTypeObject *ty, const void *p, size_t n)
   PyStringObject *x = (PyStringObject *)ty->tp_alloc(ty, n);
   if (p) memcpy(x->ob_sval, p, n);
   x->ob_sval[n] = 0;
-#ifdef CACHE_HASH
+#if defined(CACHE_HASH) || PY_VERSION_HEX >= 0x02030000
   x->ob_shash = -1;
 #endif
   x->ob_sstate = SSTATE_NOT_INTERNED;
@@ -54,19 +54,76 @@ static PyObject *bytestring_pynew(PyTypeObject *ty,
                                  PyObject *arg, PyObject *kw)
 {
   const char *p;
-  int n;
+  Py_ssize_t n;
   static char *kwlist[] = { "data", 0 };
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &p, &n))
     return (0);
   return (dowrap(ty, p, n));
 }
 
+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))
+    goto end;
+  if (psz == qsz && ct_memeq(p, q, psz)) RETURN_TRUE;
+  else RETURN_FALSE;
+end:
+  return (0);
+}
+
+static PyObject *meth__ByteString_zero(PyObject *me, PyObject *arg)
+{
+  size_t sz;
+  PyObject *rc = 0;
+  if (!PyArg_ParseTuple(arg, "OO&:zero", &me, convszt, &sz)) goto end;
+  rc = bytestring_pywrap(0, sz);
+  memset(PyString_AS_STRING(rc), 0, sz);
+end:
+  return (rc);
+}
+
+static PyObject *bytestring_pyrichcompare(PyObject *me,
+                                         PyObject *you, int op)
+{
+  int b;
+  void *mystr, *yourstr;
+  Py_ssize_t mylen, yourlen, 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);
+
+  switch (op) {
+    case Py_EQ:
+      b = mylen == yourlen && ct_memeq(mystr, yourstr, mylen);
+      break;
+    case Py_NE:
+      b = mylen != yourlen || !ct_memeq(mystr, yourstr, mylen);
+      break;
+    default:
+      minlen = mylen < yourlen ? mylen : yourlen;
+      b = memcmp(mystr, yourstr, minlen);
+      if (!b) b = mylen < yourlen ? -1 : mylen > yourlen ? +1 : 0;
+      switch (op) {
+       case Py_LT: b = b <  0; break;
+       case Py_LE: b = b <= 0; break;
+       case Py_GE: b = b >= 0; break;
+       case Py_GT: b = b >  0; break;
+       default: abort();
+      }
+  }
+  if (b) RETURN_TRUE;
+  else RETURN_FALSE;
+}
+
 #define BINOP(name, op)                                                        \
   static PyObject *bytestring_py##name(PyObject *x, PyObject *y) {     \
     const void *xv, *yv;                                               \
     const unsigned char *xp, *yp;                                      \
     unsigned char *zp;                                                 \
-    int xsz, ysz;                                                      \
+    Py_ssize_t xsz, ysz;                                               \
     int i;                                                             \
     PyObject *rc = 0;                                                  \
     if (PyObject_AsReadBuffer(x, &xv, &xsz) ||                         \
@@ -88,7 +145,7 @@ BINOP(xor, ^)
     const void *xv;                                                    \
     const unsigned char *xp;                                           \
     unsigned char *zp;                                                 \
-    int xsz;                                                           \
+    Py_ssize_t xsz;                                                    \
     int i;                                                             \
     PyObject *rc = 0;                                                  \
     if (PyObject_AsReadBuffer(x, &xv, &xsz)) goto end;                 \
@@ -130,7 +187,7 @@ static PyBufferProcs bytestring_pybuffer;
 
 static PyTypeObject bytestring_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ByteString",               /* @tp_name@ */
+  "ByteString",                                /* @tp_name@ */
   0,                                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -158,7 +215,7 @@ static PyTypeObject bytestring_pytype_skel = {
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
-  0,                                   /* @tp_richcompare@ */
+  bytestring_pyrichcompare,            /* @tp_richcompare@ */
   0,                                   /* @tp_weaklistoffset@ */
   0,                                   /* @tp_iter@ */
   0,                                   /* @tp_iternext@ */
@@ -179,10 +236,19 @@ static PyTypeObject bytestring_pytype_skel = {
 
 /*----- Initialization ----------------------------------------------------*/
 
+static PyMethodDef methods[] = {
+#define METHNAME(func) meth_##func
+  METH  (ctstreq,              "ctstreq(S, T) -> BOOL")
+  METH (_ByteString_zero,      "zero(N) -> 0000...00")
+#undef METHNAME
+  { 0 }
+};
+
 #define string_pytype &PyString_Type
 void bytestring_pyinit(void)
 {
   INITTYPE(bytestring, string);
+  addmethods(methods);
 }
 
 void bytestring_pyinsert(PyObject *mod)