MS

 view release on metacpan or  search on metacpan

lib/MS/Reader/XML.pm  view on Meta::CPAN


    # Everything else
    else {  
        $self->{_curr_ref}->{$el} = $new_ref;
    }

    # Step up linked list
    $self->{_curr_ref} = $new_ref;

    return;

}

sub _handle_end {

    my ($self, $p, $el) = @_;

    # Track length of indexed elements
    if (defined $self->{_make_index}->{$el}) {
        my $iter = scalar @{ $self->{_curr_ref}->{__offsets} } - 1;
        my $offset = $self->{_curr_ref}->{__offsets}->[$iter];

        my $len = $p->current_byte - $offset;
        # Don't forget to add length of tag and "</>" chars
        # if an element is not empty (i.e. if it has a closing tag).
        # There may be a better way to deduce this based on the parser itself,
        # but current empty elements must be defined in the subclass itself.
        if (! defined $self->{_empty_el}->{$el}) {
            $len += length($el) + 3;
        }
        $self->{_curr_ref}->{__lengths}->[$iter] = $len;

    }

    # Reset handlers for skipped elements
    if (defined $self->{_skip_inside}->{$el}) {
        $p->setHandlers(
            Start => sub{ $self->_handle_start( @_) },
            End   => sub{ $self->_handle_end( @_) },
            Char  => sub{ $self->_handle_char( @_) },
        );
        delete $self->{_skip_parse};
        return;
    }

    # Don't do anything if inside skipped element
    return if ($self->{_skip_parse});

    # Step back down linked list
    my $last_ref = $self->{_curr_ref}->{_back};
    delete $self->{_curr_ref}->{_back};
    $self->{_curr_ref} = $last_ref;

    return;

}

sub _handle_char {

    my ($self, $p, $data) = @_;
    $self->{_curr_ref}->{pcdata} .= $data
        if ($data =~ /\S/);
    return;

}

sub goto {

    my ($self, $ref, $idx) = @_;
    croak "Bad list ref" if (! exists $ref->{__pos});
    croak "$idx not an integer" if ($idx =~ /\D/);
    # $idx allowed to be equal to count because this indicates end-of-records
    croak "$idx out of range" if ($idx < 0 || $idx > $ref->{__count});
    $ref->{__pos} = $idx;
    return;

}

sub fetch_record {

    my ($self, $ref, $idx, %args) = @_;

    croak "Bad list ref" if (! exists $ref->{__pos});
    
    # check record cache if used
    return $ref->{__memoized}->{$idx}
        if ($self->{__use_cache} && exists $ref->{__memoized}->{$idx});

    my $offset = $ref->{__offsets}->[ $idx ];
    croak "Record not found for $idx" if (! defined $offset);

    my $to_read = $ref->{__lengths}->[ $idx ];
    my $el   = $self->_read_element($offset,$to_read);

    my $type = $ref->{__record_type};
    my $class = $self->{__record_classes}->{$type};
    croak "No class defined for record type $type\n" if (! defined $class);
    my $record = $class->new( xml => $el,
        use_cache => $self->{__use_cache}, %args );

    # cache record if necessary
    if ($self->{__use_cache}) {
        #dunlock($ref);
        $ref->{__memoized}->{$idx} = $record;
        #dlock($ref);
    }
    
    return $record;

}

sub next_record {

    my ($self, $ref, %args) = @_;

    my $pos = $ref->{__pos};
    return if ($pos == $ref->{__count}); #EOF

    my $record;

    # There is a while loop here because a return value of -1 from



( run in 2.190 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )