ec.c (ecptxl_1): Accept any iterable of coordinates.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 25 Nov 2019 13:29:39 +0000 (13:29 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 25 Nov 2019 17:51:34 +0000 (17:51 +0000)
ec.c

diff --git a/ec.c b/ec.c
index 74bbf5e..04bd482 100644 (file)
--- a/ec.c
+++ b/ec.c
@@ -513,9 +513,8 @@ end:
 static int ecptxl_1(ec_curve *c, ec *p, PyObject *x)
 {
   int rc = -1;
-  PyObject *y = 0, *z = 0, *t = 0;
+  PyObject *y = 0, *z = 0, *t = 0, *u = 0;
   mp *xx = 0;
-  int n;
   qd_parse qd;
   int paren;
 
@@ -536,27 +535,33 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x)
   } else if (c && (xx = tomp(x)) != 0) {
     xx = F_IN(c->f, xx, xx);
     if (!EC_FIND(c, p, xx)) VALERR("not on the curve");
-  } else if (PySequence_Check(x)) {
-    t = x; x = 0;
-    n = PySequence_Size(t); if (n < 0) goto end;
-    if (n != 2 && n != 3)
-      TYERR("want sequence of two or three items");
-    if ((x = PySequence_GetItem(t, 0)) == 0 ||
-       (y = PySequence_GetItem(t, 1)) == 0 ||
-       (n == 3 && (z = PySequence_GetItem(t, 2)) == 0))
-      goto end;
-    rc = (n == 2) ? ecptxl_2(c, p, x, y) : ecptxl_3(c, p, x, y, z);
+  } else if ((t = PyObject_GetIter(x)) != 0) {
+    Py_DECREF(x);
+    x = PyIter_Next(t); if (!x) goto enditer;
+    y = PyIter_Next(t); if (!y) goto enditer;
+    z = PyIter_Next(t); if (!z && PyErr_Occurred()) goto end;
+    if (z) {
+      u = PyIter_Next(t);
+      if (u) goto enditer;
+      else if (PyErr_Occurred()) goto end;
+    }
+    rc = !z ? ecptxl_2(c, p, x, y) : ecptxl_3(c, p, x, y, z);
     goto end;
-  } else
+  } else {
+    PyErr_Clear();
     TYERR("can't convert to curve point");
+  }
   goto ok;
 
+enditer:
+  if (PyErr_Occurred()) goto end;
+  TYERR("expected sequence of 2 or 3 items");
 fix:
   if (c) EC_IN(c, p, p);
 ok:
   rc = 0;
 end:
-  Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(z); Py_XDECREF(t);
+  Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(z); Py_XDECREF(t); Py_XDECREF(u);
   mp_drop(xx);
   return (rc);
 }