Class MUES::PolymorphicObject
In: ext/object.c  (CVS)
Parent: mues_cMuesObject

Initializer

Methods

polymorph  

Constants

Rcsid = rcsstr
Version = vstr

Public Instance methods

polymorph( other ) -> anObject


Cause the receiver to switch itself with the specified other MUES::PolymorphicObject. A SecurityError will be raised if $SAFE is greater than 0 and only one of the objects is tainted, or if $SAFE is 4 or greater and either of the objects are tainted. Returns the new receiver.

[Source]

/*
 * polymorph( other ) -> anObject
 * ---
 * Cause the receiver to switch itself with the specified +other+
 * MUES::PolymorphicObject. A SecurityError will be raised if $SAFE is greater
 * than 0 and only one of the objects is tainted, or if $SAFE is 4 or greater
 * and either of the objects are tainted. Returns the new receiver.
 */
static VALUE
mues_polymorphic_polymorph( self, other ) 
     VALUE self, other;
{
    long t[5];

    // Restrict what self can polymorph in $SAFE >= 1.
    if ( rb_safe_level() >= 1 ) {
        if ( OBJ_TAINTED(self) && !OBJ_TAINTED(other) )
            rb_raise( rb_eSecurityError, "Insecure: can't polymorph into an untainted object." );
        if ( !OBJ_TAINTED(self) && OBJ_TAINTED(other) )
            rb_raise( rb_eSecurityError, "Insecure: can't polymorph into a tainted object." );

        // Objects can't polymorph at all in $SAFE >= 4.
        if ( rb_safe_level() >= 4 && (OBJ_TAINTED( self ) || OBJ_TAINTED( other )) )
            rb_raise( rb_eSecurityError, "Insecure: cannot polymorph a tainted object." );
    }

    // Check to make sure the other object is also polymorphic
    if ( !rb_obj_is_kind_of(other, mues_cMuesPolymorphicObject) )
        rb_raise( rb_eTypeError, "Cannot polymorph a non-polymorphic object.",
                  rb_class2name(CLASS_OF( other )) );

    // Make sure both objects are real objects (this shouldn't be a concern, as
    // they should all be PolymorphicObjects, but better safe than sorry).
    if ( IMMEDIATE_P(self) )
        rb_raise( rb_eTypeError, "%s is not boxed",
                  rb_class2name(CLASS_OF( self )) );
    if ( IMMEDIATE_P(other) )
        rb_raise( rb_eTypeError, "%s is not boxed",
                  rb_class2name(CLASS_OF( other )) );

    // Exchange the ids of the two objects
    memcpy( (long *)t    , (long *)self , 5 * sizeof(long) );
    memcpy( (long *)self , (long *)other, 5 * sizeof(long) );
    memcpy( (long *)other, (long *)t    , 5 * sizeof(long) );

    return self;
}

[Validate]