# class Object::Syck::Resolver

Define YAML::Syck::Resolver class

### Attributes

tags[RW]

### Public Class Methods

new() click to toggle source

YAML::Syck::Resolver.initialize

    static VALUE
    syck_resolver_initialize(VALUE self)
    {
        rb_ivar_set(self, s_tags, rb_hash_new());
        return self;
    }

### Public Instance Methods

add_type(p1, p2) click to toggle source

YAML::Syck::Resolver#add_type

    VALUE
    syck_resolver_add_type(VALUE self, VALUE taguri, VALUE cls)
    {
        VALUE tags = rb_attr_get(self, s_tags);
        rb_hash_aset( tags, taguri, cls );
        return Qnil;
    }

detect_implicit(p1) click to toggle source

YAML::Syck::Resolver#detect_implicit

    VALUE
    syck_resolver_detect_implicit(VALUE self, VALUE val)
    {
        return rb_str_new2( "" );
    }

node_import(p1) click to toggle source

YAML::Syck::Resolver#node_import

    VALUE
    syck_resolver_node_import(VALUE self, VALUE node)
    {
        SyckNode *n;
        VALUE obj = Qnil;
        int i = 0;
        Data_Get_Struct(node, SyckNode, n);

        switch (n->kind)
        {
            case syck_str_kind:
                obj = rb_str_new( n->data.str->ptr, n->data.str->len );
            break;

            case syck_seq_kind:
                obj = rb_ary_new2( n->data.list->idx );
                for ( i = 0; i < n->data.list->idx; i++ )
                {
                    rb_ary_store( obj, i, syck_seq_read( n, i ) );
                }
            break;

            case syck_map_kind:
                obj = rb_hash_new();
                for ( i = 0; i < n->data.pairs->idx; i++ )
                {
                    VALUE k = syck_map_read( n, map_key, i );
                    VALUE v = syck_map_read( n, map_value, i );
                    int skip_aset = 0;

                    /*
                     * Handle merge keys
                     */
                    if ( rb_obj_is_kind_of( k, cMergeKey ) )
                    {
                        if ( rb_obj_is_kind_of( v, rb_cHash ) )
                        {
                            VALUE dup = rb_funcall( v, s_dup, 0 );
                            rb_funcall( dup, s_update, 1, obj );
                            obj = dup;
                            skip_aset = 1;
                        }
                        else if ( rb_obj_is_kind_of( v, rb_cArray ) )
                        {
                            VALUE end = rb_ary_pop( v );
                            if ( rb_obj_is_kind_of( end, rb_cHash ) )
                            {
                                VALUE dup = rb_funcall( end, s_dup, 0 );
                                v = rb_ary_reverse( v );
                                rb_ary_push( v, obj );
                                rb_block_call( v, s_each, 0, 0, syck_merge_i, dup );
                                obj = dup;
                                skip_aset = 1;
                            }
                        }
                    }
                    else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
                    {
                        rb_funcall( obj, s_default_set, 1, v );
                        skip_aset = 1;
                    }

                    if ( ! skip_aset )
                    {
                        rb_hash_aset( obj, k, v );
                    }
                }
            break;
        }

        if ( n->type_id != NULL )
        {
            obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
        }
        return obj;
    }

tagurize(p1) click to toggle source

YAML::Syck::Resolver#tagurize

    VALUE
    syck_resolver_tagurize(VALUE self, VALUE val)
    {
        VALUE tmp = rb_check_string_type(val);

        if ( !NIL_P(tmp) )
        {
            char *taguri = syck_type_id_to_uri( RSTRING_PTR(tmp) );
            val = rb_str_new2( taguri );
            S_FREE( taguri );
        }

        return val;
    }

transfer(p1, p2) click to toggle source

YAML::Syck::Resolver#transfer

    VALUE
    syck_resolver_transfer(VALUE self, VALUE type, VALUE val)
    {
        if (NIL_P(type) || RSTRING_LEN(StringValue(type)) == 0)
        {
            type = rb_funcall( self, s_detect_implicit, 1, val );
        }

        if ( ! (NIL_P(type) || RSTRING_LEN(StringValue(type)) == 0) )
        {
            VALUE str_xprivate = rb_str_new2( "x-private" );
            VALUE colon = rb_str_new2( ":" );
            VALUE tags = rb_attr_get(self, s_tags);
            VALUE target_class = rb_hash_aref( tags, type );
            VALUE subclass = target_class;
            VALUE obj = Qnil;

            /*
             * Should no tag match exactly, check for subclass format
             */
            if ( NIL_P( target_class ) )
            {
                VALUE subclass_parts = rb_ary_new();
                VALUE parts = rb_str_split( type, ":" );

                while ( RARRAY_LEN(parts) > 1 )
                {
                    VALUE partial;
                    rb_ary_unshift( subclass_parts, rb_ary_pop( parts ) );
                    partial = rb_ary_join( parts, colon );
                    target_class = rb_hash_aref( tags, partial );
                    if ( NIL_P( target_class ) )
                    {
                        rb_str_append( partial, colon );
                        target_class = rb_hash_aref( tags, partial );
                    }

                    /*
                     * Possible subclass found, see if it supports subclassing
                     */
                    if ( ! NIL_P( target_class ) )
                    {
                        subclass = target_class;
                        if ( RARRAY_LEN(subclass_parts) > 0 && rb_respond_to( target_class, s_tag_subclasses ) &&
                             RTEST( rb_funcall( target_class, s_tag_subclasses, 0 ) ) )
                        {
                            VALUE subclass_v;
                            subclass = rb_ary_join( subclass_parts, colon );
                            subclass = rb_funcall( target_class, s_tag_read_class, 1, subclass );
                            subclass_v = syck_const_find( subclass );

                            if ( subclass_v != Qnil )
                            {
                                subclass = subclass_v;
                            }
                            else if ( rb_cObject == target_class && subclass_v == Qnil )
                            {
                                target_class = cYObject;
                                type = subclass;
                                subclass = cYObject;
                            }
                            else /* workaround for SEGV. real fix please */
                            {
                                rb_raise( rb_eTypeError, "invalid subclass" );
                            }
                        }
                        break;
                    }
                }
            }

            /* rb_raise(rb_eTypeError, "invalid typing scheme: %s given",
             *         scheme);
             */

            if ( rb_respond_to( target_class, s_call ) )
            {
                obj = rb_funcall( target_class, s_call, 2, type, val );
            }
            else
            {
                if ( rb_respond_to( target_class, s_yaml_new ) )
                {
                    obj = rb_funcall( target_class, s_yaml_new, 3, subclass, type, val );
                }
                else if ( !NIL_P( target_class ) )
                {
    #ifdef RUBY_INTEGER_UNIFICATION
                    if ( subclass == rb_cInteger )
    #else
                    if ( subclass == rb_cBignum )
    #endif
                    {
                        obj = rb_str2inum( val, 10 ); /* for yaml dumped by 1.8.3 [ruby-core:6159] */
                    }
                    else
                    {
                        obj = rb_obj_alloc( subclass );
                    }

                    if ( rb_respond_to( obj, s_yaml_initialize ) )
                    {
                        rb_funcall( obj, s_yaml_initialize, 2, type, val );
                    }
                    else if ( !NIL_P( obj ) && rb_obj_is_instance_of( val, rb_cHash ) )
                    {
                        rb_block_call( val, s_each, 0, 0, syck_set_ivars, obj );
                    }
                }
                else
                {
                    VALUE parts = rb_str_split( type, ":" );
                    VALUE scheme = rb_ary_shift( parts );
                    if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
                    {
                        VALUE name = rb_ary_join( parts, colon );
                        obj = rb_funcall( cPrivateType, s_new, 2, name, val );
                    }
                    else
                    {
                        VALUE domain = rb_ary_shift( parts );
                        VALUE name = rb_ary_join( parts, colon );
                        obj = rb_funcall( cDomainType, s_new, 3, domain, name, val );
                    }
                }
            }
            val = obj;
        }

        return val;
    }

use_types_at(p1) click to toggle source

YAML::Syck::Resolver#use_types_at

    VALUE
    syck_resolver_use_types_at(VALUE self, VALUE hsh)
    {
        rb_ivar_set( self, s_tags, hsh );
        return Qnil;
    }