Skip to content

Commit

Permalink
Clean up the __of__method a bit.
Browse files Browse the repository at this point in the history
  • Loading branch information
stephan-hof committed Feb 22, 2017
1 parent 500c389 commit f9585d0
Showing 1 changed file with 44 additions and 40 deletions.
84 changes: 44 additions & 40 deletions src/Acquisition/_Acquisition.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,14 @@ static PyExtensionClass Wrappertype, XaqWrappertype;

#define isWrapper(o) (isImplicitWrapper(o) || isExplicitWrapper(o))

/* Same as isWrapper but does a check for NULL pointer. */
#define XisWrapper(o) ((o) ? isWrapper(o) : 0)

#define WRAPPER(O) ((Wrapper*)(O))

#define newWrapper(obj, container, Wrappertype) \
PyObject_CallFunctionObjArgs(OBJECT(Wrappertype), obj, container, NULL)

static int
Wrapper__init__(Wrapper *self, PyObject *args, PyObject *kwargs)
{
Expand Down Expand Up @@ -216,48 +222,49 @@ Wrapper__init__(Wrapper *self, PyObject *args, PyObject *kwargs)

/* ---------------------------------------------------------------- */

/* Creates a new Wrapper object with the values from the old one.
* Steals a reference from 'ob' (also in the error case).
* Returns a new reference.
* Returns NULL on error.
*/
static PyObject *
clone_wrapper(Wrapper *ob)
{
PyObject *tmp;

/* Only clone if its shared with others. */
if (Py_REFCNT(ob) == 1) {
return (PyObject*) ob;
}

tmp = newWrapper(ob->obj, ob->container, Py_TYPE(ob));
Py_DECREF(ob);
return tmp;
}

static PyObject *
__of__(PyObject *inst, PyObject *parent)
{
PyObject *r, *t;

UNLESS(r=PyObject_GetAttr(inst, py__of__)) return NULL;
UNLESS(t=PyTuple_New(1)) goto err;
Py_INCREF(parent);
PyTuple_SET_ITEM(t,0,parent);
ASSIGN(r,PyObject_CallObject(r,t));
Py_DECREF(t);

if (r != NULL
&& isWrapper(r)
&& WRAPPER(r)->container && isWrapper(WRAPPER(r)->container)
)
while (WRAPPER(r)->obj && isWrapper(WRAPPER(r)->obj)
&& (WRAPPER(WRAPPER(r)->obj)->container ==
WRAPPER(WRAPPER(r)->container)->obj)
)
{
if (r->ob_refcnt !=1 )
{
t = PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(r),
WRAPPER(r)->obj,
WRAPPER(r)->container,
NULL);
Py_DECREF(r);
if (t==NULL)
return NULL;
r = t;
}
PyObject *result;
result = PyObject_CallMethodObjArgs(inst, py__of__, parent, NULL);

/* Simplify wrapper */
Py_XINCREF(WRAPPER(WRAPPER(r)->obj)->obj);
ASSIGN(WRAPPER(r)->obj, WRAPPER(WRAPPER(r)->obj)->obj);
}
if (XisWrapper(result) && XisWrapper(WRAPPER(result)->container)) {
while (XisWrapper(WRAPPER(result)->obj) &&
(WRAPPER(WRAPPER(result)->obj)->container ==
WRAPPER(WRAPPER(result)->container)->obj)) {

return r;
err:
Py_DECREF(r);
return NULL;
/* Copy it, because the result could be shared with others. */
if ((result = clone_wrapper(WRAPPER(result))) == NULL) {
return NULL;
}

/* Simplify wrapper */
Py_XINCREF(WRAPPER(WRAPPER(result)->obj)->obj);
ASSIGN(WRAPPER(result)->obj, WRAPPER(WRAPPER(result)->obj)->obj);
}
}

return result;
}

static PyObject *
Expand All @@ -274,9 +281,6 @@ Wrapper_descrget(Wrapper *self, PyObject *inst, PyObject *cls)
}


#define newWrapper(obj, container, Wrappertype) \
PyObject_CallFunctionObjArgs(OBJECT(Wrappertype), obj, container, NULL)


static int
Wrapper_traverse(Wrapper *self, visitproc visit, void *arg)
Expand Down

0 comments on commit f9585d0

Please sign in to comment.