chiark / gitweb /
*.c: Introduce a new input conversion for binary strings.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 21 Oct 2019 00:43:54 +0000 (01:43 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 11 Apr 2020 11:44:21 +0000 (12:44 +0100)
One of the major differences in Python 3 is that it firmly distinguishes
between binary and text strings: the former consist of small integers,
while the latter consist of Unicode scalars.  The Python 3 `s#'
conversion's main purpose is to accept text strings, and though it will
also accept binary strings it's not really ideal for the purpose.
Python 3 introduces a new conversion `y#' specifically for binary
strings, though this isn't quite what we want because, for some reason,
it /doesn't/ work with bufferish objects which require explicit release.

The best answer seems to be to introduce our own custom conversion for
binary strings, so we do this here, replacing all of the binary-input
argument conversions.  While we're at it, replace all of the by-steam
argument conversions using `PyObject_AsReadBuffer' too.

pyke.c
pyke.h

diff --git a/pyke.c b/pyke.c
index 29dd8c51ae178b2d2c5e32f65544d0b4fd620da7..d874763b760f611e037b8ca653a215e96969e1be 100644 (file)
--- a/pyke.c
+++ b/pyke.c
@@ -101,6 +101,25 @@ end:
   return (0);
 }
 
+int convbin(PyObject *o, void *pp)
+{
+  struct bin *r = pp;
+
+  if (PyString_Check(o)) {
+    r->p = PyString_AS_STRING(o);
+    r->sz = PyString_GET_SIZE(o);
+    return (1);
+  }
+  if (PyUnicode_Check(o)) {
+    o = _PyUnicode_AsDefaultEncodedString(o, 0);
+    if (!o) return (0);
+    r->p = PyString_AS_STRING(o);
+    r->sz = PyString_GET_SIZE(o);
+    return (1);
+  }
+  return (PyObject_AsReadBuffer(o, &r->p, &r->sz) ? 0 : 1);
+}
+
 /*----- Miscellaneous utilities -------------------------------------------*/
 
 PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
diff --git a/pyke.h b/pyke.h
index 6c4e4e125964a0f7907f33df558d352426d9948b..984b5d553a03e5161c13f46ba674734d4c7dc2ef 100644 (file)
--- a/pyke.h
+++ b/pyke.h
@@ -169,10 +169,12 @@ extern void restore_exception(struct excinfo *, const char *, ...);
 /* Input conversion functions for standard kinds of objects, with overflow
  * checking where applicable.
  */
+struct bin { const void *p; Py_ssize_t sz; };
 extern int convulong(PyObject *, void *); /* unsigned long */
 extern int convuint(PyObject *, void *); /* unsigned int */
 extern int convszt(PyObject *, void *);        /* size_t */
 extern int convbool(PyObject *, void *); /* bool */
+extern int convbin(PyObject *, void *); /* read buffer holding bytes */
 
 /* Output conversions. */
 extern PyObject *getbool(int);         /* bool */