MARC-Record
view release on metacpan or search on metacpan
lib/MARC/File/USMARC.pm view on Meta::CPAN
$marc->_warn( "field does not end in end of field character in tag $tagno $location" );
}
warn "Specs: ", join( "|", $tagno, $len, $offset, $tagdata ), "\n" if $MARC::Record::DEBUG;
if ( $filter_func ) {
next unless $filter_func->( $tagno, $tagdata );
}
if ( MARC::Field->is_controlfield_tag($tagno) ) {
$marc->append_fields( MARC::Field->new( $tagno, $tagdata ) );
} else {
my @subfields = split( SUBFIELD_INDICATOR, $tagdata );
my $indicators = shift @subfields;
my ($ind1, $ind2);
if ( length( $indicators ) > 2 or length( $indicators ) == 0 ) {
$marc->_warn( "Invalid indicators \"$indicators\" forced to blanks $location for tag $tagno\n" );
($ind1,$ind2) = (" ", " ");
} else {
$ind1 = substr( $indicators,0, 1 );
$ind2 = substr( $indicators,1, 1 );
}
# Split the subfield data into subfield name and data pairs
my @subfield_data;
for ( @subfields ) {
if ( length > 0 ) {
push( @subfield_data, substr($_,0,1),substr($_,1) );
} else {
$marc->_warn( "Entirely empty subfield found in tag $tagno" );
}
}
if ( !@subfield_data ) {
$marc->_warn( "no subfield data found $location for tag $tagno" );
next;
}
my $field = MARC::Field->new($tagno, $ind1, $ind2, @subfield_data );
if ( $field->warnings() ) {
$marc->_warn( $field->warnings() );
}
$marc->append_fields( $field );
}
} # looping through all the fields
return $marc;
}
=head2 update_leader()
If any changes get made to the MARC record, the first 5 bytes of the
leader (the length) will be invalid. This function updates the
leader with the correct length of the record as it would be if
written out to a file.
=cut
sub update_leader {
my $self = shift;
my (undef,undef,$reclen,$baseaddress) = $self->_build_tag_directory();
$self->_set_leader_lengths( $reclen, $baseaddress );
}
=head2 _build_tag_directory()
Function for internal use only: Builds the tag directory that gets
put in front of the data in a MARC record.
Returns two array references, and two lengths: The tag directory, and the data fields themselves,
the length of all data (including the Leader that we expect will be added),
and the size of the Leader and tag directory.
=cut
sub _build_tag_directory {
my $marc = shift;
$marc = shift if (ref($marc)||$marc) =~ /^MARC::File/;
die "Wanted a MARC::Record but got a ", ref($marc) unless ref($marc) eq "MARC::Record";
my @fields;
my @directory;
my $dataend = 0;
for my $field ( $marc->fields() ) {
# Dump data into proper format
my $str = $field->as_usmarc;
push( @fields, $str );
# Create directory entry
my $len = bytes::length( $str );
my $direntry = sprintf( "%03s%04d%05d", $field->tag, $len, $dataend );
push( @directory, $direntry );
$dataend += $len;
}
my $baseaddress =
LEADER_LEN + # better be 24
( @directory * DIRECTORY_ENTRY_LEN ) +
# all the directory entries
1; # end-of-field marker
my $total =
$baseaddress + # stuff before first field
$dataend + # Length of the fields
1; # End-of-record marker
return (\@fields, \@directory, $total, $baseaddress);
}
=head2 encode()
Returns a string of characters suitable for writing out to a USMARC file,
( run in 2.009 seconds using v1.01-cache-2.11-cpan-98e64b0badf )