← Index
NYTProf Performance Profile   « block view • line view • sub view »
For conv.pl
  Run on Sun Nov 14 21:14:18 2010
Reported on Sun Nov 14 21:17:53 2010

Filename/usr/share/perl5/MARC/File/USMARC.pm
StatementsExecuted 552281 statements in 2.18s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
5000112.14s7.47sMARC::File::USMARC::::_build_tag_directoryMARC::File::USMARC::_build_tag_directory
500011274ms7.92sMARC::File::USMARC::::encodeMARC::File::USMARC::encode
100002121.0ms21.0msMARC::File::USMARC::::CORE:matchMARC::File::USMARC::CORE:match (opcode)
111335µs810µsMARC::File::USMARC::::BEGIN@13MARC::File::USMARC::BEGIN@13
11128µs39µsMARC::File::USMARC::::BEGIN@9MARC::File::USMARC::BEGIN@9
11119µs24µsMARC::File::USMARC::::BEGIN@10MARC::File::USMARC::BEGIN@10
11118µs108µsMARC::File::USMARC::::BEGIN@19MARC::File::USMARC::BEGIN@19
11116µs79µsMARC::File::USMARC::::BEGIN@12MARC::File::USMARC::BEGIN@12
11116µs82µsMARC::File::USMARC::::BEGIN@18MARC::File::USMARC::BEGIN@18
11115µs89µsMARC::File::USMARC::::BEGIN@21MARC::File::USMARC::BEGIN@21
11115µs82µsMARC::File::USMARC::::BEGIN@20MARC::File::USMARC::BEGIN@20
11114µs59µsMARC::File::USMARC::::BEGIN@16MARC::File::USMARC::BEGIN@16
11114µs14µsMARC::File::USMARC::::BEGIN@15MARC::File::USMARC::BEGIN@15
11114µs79µsMARC::File::USMARC::::BEGIN@22MARC::File::USMARC::BEGIN@22
0000s0sMARC::File::USMARC::::_nextMARC::File::USMARC::_next
0000s0sMARC::File::USMARC::::decodeMARC::File::USMARC::decode
0000s0sMARC::File::USMARC::::update_leaderMARC::File::USMARC::update_leader
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package MARC::File::USMARC;
2
3=head1 NAME
4
- -
9345µs250µs
# spent 39µs (28+11) within MARC::File::USMARC::BEGIN@9 which was called: # once (28µs+11µs) by MARC::Record::as_usmarc at line 9
use strict;
# spent 39µs making 1 call to MARC::File::USMARC::BEGIN@9 # spent 11µs making 1 call to strict::import
10352µs229µs
# spent 24µs (19+5) within MARC::File::USMARC::BEGIN@10 which was called: # once (19µs+5µs) by MARC::Record::as_usmarc at line 10
use integer;
# spent 24µs making 1 call to MARC::File::USMARC::BEGIN@10 # spent 5µs making 1 call to integer::import
11
123140µs2142µs
# spent 79µs (16+63) within MARC::File::USMARC::BEGIN@12 which was called: # once (16µs+63µs) by MARC::Record::as_usmarc at line 12
use vars qw( $ERROR );
# spent 79µs making 1 call to MARC::File::USMARC::BEGIN@12 # spent 63µs making 1 call to vars::import
133167µs2886µs
# spent 810µs (335+475) within MARC::File::USMARC::BEGIN@13 which was called: # once (335µs+475µs) by MARC::Record::as_usmarc at line 13
use MARC::File::Encode qw( marc_to_utf8 );
# spent 810µs making 1 call to MARC::File::USMARC::BEGIN@13 # spent 76µs making 1 call to Exporter::import
14
15345µs114µs
# spent 14µs within MARC::File::USMARC::BEGIN@15 which was called: # once (14µs+0s) by MARC::Record::as_usmarc at line 15
use MARC::File;
# spent 14µs making 1 call to MARC::File::USMARC::BEGIN@15
16465µs2104µs
# spent 59µs (14+45) within MARC::File::USMARC::BEGIN@16 which was called: # once (14µs+45µs) by MARC::Record::as_usmarc at line 16
use vars qw( @ISA ); @ISA = qw( MARC::File );
# spent 59µs making 1 call to MARC::File::USMARC::BEGIN@16 # spent 45µs making 1 call to vars::import
17
18353µs2148µs
# spent 82µs (16+66) within MARC::File::USMARC::BEGIN@18 which was called: # once (16µs+66µs) by MARC::Record::as_usmarc at line 18
use MARC::Record qw( LEADER_LEN );
# spent 82µs making 1 call to MARC::File::USMARC::BEGIN@18 # spent 66µs making 1 call to Exporter::import
19355µs2198µs
# spent 108µs (18+90) within MARC::File::USMARC::BEGIN@19 which was called: # once (18µs+90µs) by MARC::Record::as_usmarc at line 19
use constant SUBFIELD_INDICATOR => "\x1F";
# spent 108µs making 1 call to MARC::File::USMARC::BEGIN@19 # spent 90µs making 1 call to constant::import
20346µs2149µs
# spent 82µs (15+67) within MARC::File::USMARC::BEGIN@20 which was called: # once (15µs+67µs) by MARC::Record::as_usmarc at line 20
use constant END_OF_FIELD => "\x1E";
# spent 82µs making 1 call to MARC::File::USMARC::BEGIN@20 # spent 67µs making 1 call to constant::import
21341µs2163µs
# spent 89µs (15+74) within MARC::File::USMARC::BEGIN@21 which was called: # once (15µs+74µs) by MARC::Record::as_usmarc at line 21
use constant END_OF_RECORD => "\x1D";
# spent 89µs making 1 call to MARC::File::USMARC::BEGIN@21 # spent 74µs making 1 call to constant::import
2231.65ms2144µs
# spent 79µs (14+65) within MARC::File::USMARC::BEGIN@22 which was called: # once (14µs+65µs) by MARC::Record::as_usmarc at line 22
use constant DIRECTORY_ENTRY_LEN => 12;
# spent 79µs making 1 call to MARC::File::USMARC::BEGIN@22 # spent 65µs making 1 call to constant::import
23
24=head1 SYNOPSIS
25
- -
44sub _next {
45 my $self = shift;
46 my $fh = $self->{fh};
47
48 my $reclen;
49 return if eof($fh);
50
51 local $/ = END_OF_RECORD;
52 my $usmarc = <$fh>;
53
54 # remove illegal garbage that sometimes occurs between records
55 $usmarc =~ s/^[ \x00\x0a\x0d\x1a]+//;
56
57 return $usmarc;
58}
59
60=head2 decode( $string [, \&filter_func ] )
61
- -
96sub decode {
97
98 my $text;
99 my $location = '';
100
101 ## decode can be called in a variety of ways
102 ## $object->decode( $string )
103 ## MARC::File::USMARC->decode( $string )
104 ## MARC::File::USMARC::decode( $string )
105 ## this bit of code covers all three
106
107 my $self = shift;
108 if ( ref($self) =~ /^MARC::File/ ) {
109 $location = 'in record '.$self->{recnum};
110 $text = shift;
111 } else {
112 $location = 'in record 1';
113 $text = $self=~/MARC::File/ ? shift : $self;
114 }
115 my $filter_func = shift;
116
117 # ok this the empty shell we will fill
118 my $marc = MARC::Record->new();
119
120 # Check for an all-numeric record length
121 ($text =~ /^(\d{5})/)
122 or return $marc->_warn( "Record length \"", substr( $text, 0, 5 ), "\" is not numeric $location" );
123
124 my $reclen = $1;
125 my $realLength = bytes::length( $text );
126 $marc->_warn( "Invalid record length $location: Leader says $reclen " .
127 "bytes but it's actually $realLength" ) unless $reclen == $realLength;
128
129 (substr($text, -1, 1) eq END_OF_RECORD)
130 or $marc->_warn( "Invalid record terminator $location" );
131
132 $marc->leader( substr( $text, 0, LEADER_LEN ) );
133
134 # bytes 12 - 16 of leader give offset to the body of the record
135 my $data_start = 0 + bytes::substr( $text, 12, 5 );
136
137 # immediately after the leader comes the directory (no separator)
138 my $dir = substr( $text, LEADER_LEN, $data_start - LEADER_LEN - 1 ); # -1 to allow for \x1e at end of directory
139
140 # character after the directory must be \x1e
141 (substr($text, $data_start-1, 1) eq END_OF_FIELD)
142 or $marc->_warn( "No directory found $location" );
143
144 # all directory entries 12 bytes long, so length % 12 must be 0
145 (length($dir) % DIRECTORY_ENTRY_LEN == 0)
146 or $marc->_warn( "Invalid directory length $location" );
147
148
149 # go through all the fields
150 my $nfields = length($dir)/DIRECTORY_ENTRY_LEN;
151 for ( my $n = 0; $n < $nfields; $n++ ) {
152 my ( $tagno, $len, $offset ) = unpack( "A3 A4 A5", substr($dir, $n*DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN) );
153
154 # Check directory validity
155 ($tagno =~ /^[0-9A-Za-z]{3}$/)
156 or $marc->_warn( "Invalid tag in directory $location: \"$tagno\"" );
157
158 ($len =~ /^\d{4}$/)
159 or $marc->_warn( "Invalid length in directory $location tag $tagno: \"$len\"" );
160
161 ($offset =~ /^\d{5}$/)
162 or $marc->_warn( "Invalid offset in directory $location tag $tagno: \"$offset\"" );
163
164 ($offset + $len <= $reclen)
165 or $marc->_warn( "Directory entry $location runs off the end of the record tag $tagno" );
166
167 my $tagdata = bytes::substr( $text, $data_start+$offset, $len );
168
169 # if utf8 the we encode the string as utf8
170 if ( $marc->encoding() eq 'UTF-8' ) {
171 $tagdata = marc_to_utf8( $tagdata );
172 }
173
174 $marc->_warn( "Invalid length in directory for tag $tagno $location" )
175 unless ( $len == bytes::length($tagdata) );
176
177 if ( substr($tagdata, -1, 1) eq END_OF_FIELD ) {
178 # get rid of the end-of-tag character
179 chop $tagdata;
180 --$len;
181 } else {
182 $marc->_warn( "field does not end in end of field character in tag $tagno $location" );
183 }
184
185 warn "Specs: ", join( "|", $tagno, $len, $offset, $tagdata ), "\n" if $MARC::Record::DEBUG;
186
187 if ( $filter_func ) {
188 next unless $filter_func->( $tagno, $tagdata );
189 }
190
191 if ( ($tagno =~ /^\d+$/) && ($tagno < 10) ) {
192 $marc->append_fields( MARC::Field->new( $tagno, $tagdata ) );
193 } else {
194 my @subfields = split( SUBFIELD_INDICATOR, $tagdata );
195 my $indicators = shift @subfields;
196 my ($ind1, $ind2);
197
198 if ( length( $indicators ) > 2 or length( $indicators ) == 0 ) {
199 $marc->_warn( "Invalid indicators \"$indicators\" forced to blanks $location for tag $tagno\n" );
200 ($ind1,$ind2) = (" ", " ");
201 } else {
202 $ind1 = substr( $indicators,0, 1 );
203 $ind2 = substr( $indicators,1, 1 );
204 }
205
206 # Split the subfield data into subfield name and data pairs
207 my @subfield_data;
208 for ( @subfields ) {
209 if ( length > 0 ) {
210 push( @subfield_data, substr($_,0,1),substr($_,1) );
211 } else {
212 $marc->_warn( "Entirely empty subfield found in tag $tagno" );
213 }
214 }
215
216 if ( !@subfield_data ) {
217 $marc->_warn( "no subfield data found $location for tag $tagno" );
218 next;
219 }
220
221 my $field = MARC::Field->new($tagno, $ind1, $ind2, @subfield_data );
222 if ( $field->warnings() ) {
223 $marc->_warn( $field->warnings() );
224 }
225 $marc->append_fields( $field );
226 }
227 } # looping through all the fields
228
229
230 return $marc;
231}
232
233=head2 update_leader()
234
- -
242sub update_leader() {
243 my $self = shift;
244
245 my (undef,undef,$reclen,$baseaddress) = $self->_build_tag_directory();
246
247 $self->_set_leader_lengths( $reclen, $baseaddress );
248}
249
250=head2 _build_tag_directory()
251
- -
261
# spent 7.47s (2.14+5.33) within MARC::File::USMARC::_build_tag_directory which was called 5000 times, avg 1.49ms/call: # 5000 times (2.14s+5.33s) by MARC::File::USMARC::encode at line 311, avg 1.49ms/call
sub _build_tag_directory {
26250000148ms my $marc = shift;
26350007.74ms $marc = shift if (ref($marc)||$marc) =~ /^MARC::File/;
# spent 7.74ms making 5000 calls to MARC::File::USMARC::CORE:match, avg 2µs/call
264 die "Wanted a MARC::Record but got a ", ref($marc) unless ref($marc) eq "MARC::Record";
265
266 my @fields;
267 my @directory;
268
269 my $dataend = 0;
270500034.9ms for my $field ( $marc->fields() ) {
# spent 34.9ms making 5000 calls to MARC::Record::fields, avg 7µs/call
271 # Dump data into proper format
2724772461.75s795414.63s my $str = $field->as_usmarc;
# spent 4.63s making 79541 calls to MARC::Field::as_usmarc, avg 58µs/call
273 push( @fields, $str );
274
275 # Create directory entry
27679541263ms my $len = bytes::length( $str );
# spent 263ms making 79540 calls to bytes::length, avg 3µs/call # spent 646µs making 1 call to bytes::AUTOLOAD
277
27879541388ms my $direntry = sprintf( "%03s%04d%05d", $field->tag, $len, $dataend );
# spent 388ms making 79541 calls to MARC::Field::tag, avg 5µs/call
279 push( @directory, $direntry );
280 $dataend += $len;
281 }
282
283 my $baseaddress =
284 LEADER_LEN + # better be 24
285 ( @directory * DIRECTORY_ENTRY_LEN ) +
286 # all the directory entries
287 1; # end-of-field marker
288
289
290 my $total =
291 $baseaddress + # stuff before first field
292 $dataend + # Length of the fields
293 1; # End-of-record marker
294
- -
297 return (\@fields, \@directory, $total, $baseaddress);
298}
299
300=head2 encode()
301
- -
307
# spent 7.92s (274ms+7.64) within MARC::File::USMARC::encode which was called 5000 times, avg 1.58ms/call: # 5000 times (274ms+7.64s) by MARC::Record::as_usmarc at line 459 of MARC/Record.pm, avg 1.58ms/call
sub encode() {
30825000278ms my $marc = shift;
309500013.3ms $marc = shift if (ref($marc)||$marc) =~ /^MARC::File/;
# spent 13.3ms making 5000 calls to MARC::File::USMARC::CORE:match, avg 3µs/call
310
31150007.47s my ($fields,$directory,$reclen,$baseaddress) = _build_tag_directory($marc);
# spent 7.47s making 5000 calls to MARC::File::USMARC::_build_tag_directory, avg 1.49ms/call
3125000120ms $marc->set_leader_lengths( $reclen, $baseaddress );
# spent 120ms making 5000 calls to MARC::Record::set_leader_lengths, avg 24µs/call
313
314 # Glomp it all together
315500041.7ms return join("",$marc->leader, @$directory, END_OF_FIELD, @$fields, END_OF_RECORD);
# spent 41.7ms making 5000 calls to MARC::Record::leader, avg 8µs/call
316}
31715µs1;
318
319__END__
 
# spent 21.0ms within MARC::File::USMARC::CORE:match which was called 10000 times, avg 2µs/call: # 5000 times (13.3ms+0s) by MARC::File::USMARC::encode at line 309, avg 3µs/call # 5000 times (7.74ms+0s) by MARC::File::USMARC::_build_tag_directory at line 263, avg 2µs/call
sub MARC::File::USMARC::CORE:match; # opcode