@@ -154,6 +154,25 @@ typecast_init(PyObject *dict)
154154 return 0 ;
155155}
156156
157+ /* typecast_get_by_name - get a type object by name (slow!) */
158+
159+ static PyObject *
160+ typecast_get_by_name (unsigned char * name )
161+ {
162+ PyObject * value , * res = NULL ;
163+ int ppos = 0 ;
164+
165+ while (PyDict_Next (psyco_types , & ppos , NULL , & value )) {
166+ if (strcmp (PyString_AsString (((typecastObject * )value )-> name ),
167+ name ) == 0 ) {
168+ res = value ;
169+ break ;
170+ }
171+ }
172+
173+ /* borrowed reference */
174+ return res ;
175+ }
157176
158177/* typecast_add - add a type object to the dictionary */
159178int
@@ -179,6 +198,8 @@ typecast_add(PyObject *obj, int binary)
179198 }
180199 }
181200
201+ Dprintf ("typecast_add: base caster: %p" , type -> bcast );
202+
182203 return 0 ;
183204}
184205
@@ -196,7 +217,7 @@ static struct memberlist typecastObject_memberlist[] = {
196217/* numeric methods */
197218
198219static PyObject *
199- typecast_new (PyObject * name , PyObject * values , PyObject * cast );
220+ typecast_new (PyObject * name , PyObject * values , PyObject * cast , PyObject * base );
200221
201222static int
202223typecast_coerce (PyObject * * pv , PyObject * * pw )
@@ -207,7 +228,7 @@ typecast_coerce(PyObject **pv, PyObject **pw)
207228 args = PyTuple_New (1 );
208229 Py_INCREF (* pw );
209230 PyTuple_SET_ITEM (args , 0 , * pw );
210- coer = typecast_new (NULL , args , NULL );
231+ coer = typecast_new (NULL , args , NULL , NULL );
211232 * pw = coer ;
212233 Py_DECREF (args );
213234 Py_INCREF (* pv );
@@ -347,7 +368,7 @@ PyTypeObject typecastType = {
347368};
348369
349370static PyObject *
350- typecast_new (PyObject * name , PyObject * values , PyObject * cast )
371+ typecast_new (PyObject * name , PyObject * values , PyObject * cast , PyObject * base )
351372{
352373 typecastObject * obj ;
353374
@@ -368,7 +389,11 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast)
368389
369390 obj -> pcast = NULL ;
370391 obj -> ccast = NULL ;
371-
392+ obj -> bcast = base ;
393+
394+ if (obj -> bcast ) Py_INCREF (obj -> bcast );
395+
396+ /* FIXME: raise an exception when None is passed as Python caster */
372397 if (cast && cast != Py_None ) {
373398 Py_INCREF (cast );
374399 obj -> pcast = cast ;
@@ -382,27 +407,36 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast)
382407PyObject *
383408typecast_from_python (PyObject * self , PyObject * args , PyObject * keywds )
384409{
385- PyObject * v , * name , * cast = NULL ;
410+ PyObject * v , * name , * cast = NULL , * base = NULL ;
386411
387- static char * kwlist [] = {"values" , "name" , "castobj" , NULL };
412+ static char * kwlist [] = {"values" , "name" , "castobj" , "baseobj" , NULL };
388413
389- if (!PyArg_ParseTupleAndKeywords (args , keywds , "O!|O!O " , kwlist ,
414+ if (!PyArg_ParseTupleAndKeywords (args , keywds , "O!|O!OO " , kwlist ,
390415 & PyTuple_Type , & v ,
391416 & PyString_Type , & name ,
392- & cast )) {
417+ & cast , & base )) {
393418 return NULL ;
394419 }
395420
396- return typecast_new (name , v , cast );
421+ return typecast_new (name , v , cast , base );
397422}
398423
399424PyObject *
400425typecast_from_c (typecastObject_initlist * type )
401426{
402- PyObject * tuple ;
427+ PyObject * tuple , * base = NULL ;
403428 typecastObject * obj ;
404429 int i , len = 0 ;
405430
431+ /* before doing anything else we look for the base */
432+ if (type -> base ) {
433+ base = typecast_get_by_name (type -> base );
434+ if (!base ) {
435+ PyErr_Format (Error , "typecast base not found: %s" , type -> base );
436+ return NULL ;
437+ }
438+ }
439+
406440 while (type -> values [len ] != 0 ) len ++ ;
407441
408442 tuple = PyTuple_New (len );
@@ -411,9 +445,10 @@ typecast_from_c(typecastObject_initlist *type)
411445 for (i = 0 ; i < len ; i ++ ) {
412446 PyTuple_SET_ITEM (tuple , i , PyInt_FromLong (type -> values [i ]));
413447 }
414-
448+
449+
415450 obj = (typecastObject * )
416- typecast_new (PyString_FromString (type -> name ), tuple , NULL );
451+ typecast_new (PyString_FromString (type -> name ), tuple , NULL , base );
417452
418453 if (obj ) {
419454 obj -> ccast = type -> cast ;
@@ -425,18 +460,26 @@ typecast_from_c(typecastObject_initlist *type)
425460PyObject *
426461typecast_cast (PyObject * obj , unsigned char * str , int len , PyObject * curs )
427462{
463+ PyObject * old , * res = NULL ;
428464 typecastObject * self = (typecastObject * )obj ;
429465
466+ /* we don't incref, the caster *can't* die at this point */
467+ old = ((cursorObject * )curs )-> caster ;
468+ ((cursorObject * )curs )-> caster = obj ;
469+
430470 if (self -> ccast ) {
431471 Dprintf ("typecast_call: calling C cast function" );
432- return self -> ccast (str , len , curs );
472+ res = self -> ccast (str , len , curs );
433473 }
434474 else if (self -> pcast ) {
435475 Dprintf ("typecast_call: calling python callable" );
436- return PyObject_CallFunction (self -> pcast , "s#O" , str , len , curs );
476+ res = PyObject_CallFunction (self -> pcast , "s#O" , str , len , curs );
437477 }
438478 else {
439479 PyErr_SetString (Error , "internal error: no casting function found" );
440- return NULL ;
441480 }
481+
482+ ((cursorObject * )curs )-> caster = old ;
483+
484+ return res ;
442485}
0 commit comments