key.c: Factor out populating a `KeyDataStructured' from a mapping.
[catacomb-python] / key.c
diff --git a/key.c b/key.c
index 4f16183..0b2d351 100644 (file)
--- a/key.c
+++ b/key.c
@@ -1015,12 +1015,35 @@ static const gmap_ops keydatastruct_gmops = {
   keydatastruct_gmdelentry
 };
 
+static int populate_struct(key_data *kd, PyObject *map)
+{
+  PyObject *it = 0, *name = 0, *val = 0;
+  const char *p;
+  int rc = -1;
+
+  if (!PyMapping_Check(map)) TYERR("subkeys must be an iterable mapping");
+  if ((it = PyObject_GetIter(map)) == 0) goto end;
+  while ((name = PyIter_Next(it)) != 0) {
+    if ((p = TEXT_STR(name)) == 0 ||
+       (val = PyObject_GetItem(map, name)) == 0)
+      goto end;
+    if (!KEYDATA_PYCHECK(val))
+      TYERR("subkey objects must be instances of KeyData");
+    key_structset(kd, p, KEYDATA_KD(val));
+    Py_DECREF(name); name = 0;
+    Py_DECREF(val); val = 0;
+  }
+  if (PyErr_Occurred()) goto end;
+  rc = 0;
+end:
+  Py_XDECREF(it); Py_XDECREF(name); Py_XDECREF(val);
+  return (rc);
+}
+
 static PyObject *keydatastruct_pynew(PyTypeObject *ty,
                                     PyObject *arg, PyObject *kw)
 {
   PyObject *sub = 0;
-  PyObject *it = 0, *name = 0, *val = 0;
-  char *p;
   keydata_pyobj *me = 0;
   key_data *kd = 0;
   static const char *const kwlist[] = { "subkeys", 0 };
@@ -1028,30 +1051,11 @@ static PyObject *keydatastruct_pynew(PyTypeObject *ty,
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:new", KWLIST, &sub))
     goto end;
   kd = key_newstruct();
-  if (sub) {
-    if (!PyMapping_Check(sub))
-      TYERR("subkeys must be an iterable mapping");
-    if ((it = PyObject_GetIter(sub)) == 0)
-      goto end;
-    while ((name = PyIter_Next(it)) != 0) {
-      if ((p = TEXT_STR(name)) == 0 ||
-         (val = PyObject_GetItem(sub, name)) == 0)
-       goto end;
-      if (!KEYDATA_PYCHECK(val))
-       TYERR("subkey objects must be subclasses of KeyData");
-      key_structset(kd, p, KEYDATA_KD(val));
-      Py_DECREF(name); name = 0;
-      Py_DECREF(val); val = 0;
-    }
-    if (PyErr_Occurred())
-      goto end;
-    Py_DECREF(it); it = 0;
-  }
+  if (sub && populate_struct(kd, sub)) goto end;
   me = (keydata_pyobj *)ty->tp_alloc(ty, 0);
   me->gmops = &keydatastruct_gmops;
   me->kd = kd; kd = 0;
 end:
-  Py_XDECREF(name); Py_XDECREF(val); Py_XDECREF(it);
   if (kd) key_drop(kd);
   return ((PyObject *)me);
 }