← Index
NYTProf Performance Profile   « block view • line view • sub view »
For conv.pl
  Run on Sun Nov 14 22:50:31 2010
Reported on Sun Nov 14 22:51:22 2010

Filename/usr/share/perl5/MARC/File/USMARC.pm
StatementsExecuted 552281 statements in 2.12s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
5000112.09s7.38sMARC::File::USMARC::::_build_tag_directoryMARC::File::USMARC::_build_tag_directory
500011273ms7.80sMARC::File::USMARC::::encodeMARC::File::USMARC::encode
100002115.4ms15.4msMARC::File::USMARC::::CORE:matchMARC::File::USMARC::CORE:match (opcode)
111365µs811µsMARC::File::USMARC::::BEGIN@13MARC::File::USMARC::BEGIN@13
11122µs29µsMARC::File::USMARC::::BEGIN@9MARC::File::USMARC::BEGIN@9
11117µs59µsMARC::File::USMARC::::BEGIN@16MARC::File::USMARC::BEGIN@16
11117µs62µsMARC::File::USMARC::::BEGIN@12MARC::File::USMARC::BEGIN@12
11117µs97µsMARC::File::USMARC::::BEGIN@19MARC::File::USMARC::BEGIN@19
11117µs21µsMARC::File::USMARC::::BEGIN@10MARC::File::USMARC::BEGIN@10
11117µs80µsMARC::File::USMARC::::BEGIN@18MARC::File::USMARC::BEGIN@18
11114µs75µsMARC::File::USMARC::::BEGIN@22MARC::File::USMARC::BEGIN@22
11114µs83µsMARC::File::USMARC::::BEGIN@20MARC::File::USMARC::BEGIN@20
11113µs13µsMARC::File::USMARC::::BEGIN@15MARC::File::USMARC::BEGIN@15
11112µs81µsMARC::File::USMARC::::BEGIN@21MARC::File::USMARC::BEGIN@21
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
- -
9340µs236µs
# spent 29µs (22+7) within MARC::File::USMARC::BEGIN@9 which was called: # once (22µs+7µs) by MARC::Record::as_usmarc at line 9
use strict;
# spent 29µs making 1 call to MARC::File::USMARC::BEGIN@9 # spent 7µs making 1 call to strict::import
10347µs225µs
# spent 21µs (17+4) within MARC::File::USMARC::BEGIN@10 which was called: # once (17µs+4µs) by MARC::Record::as_usmarc at line 10
use integer;
# spent 21µs making 1 call to MARC::File::USMARC::BEGIN@10 # spent 4µs making 1 call to integer::import
11
12345µs2107µs
# spent 62µs (17+45) within MARC::File::USMARC::BEGIN@12 which was called: # once (17µs+45µs) by MARC::Record::as_usmarc at line 12
use vars qw( $ERROR );
# spent 62µs making 1 call to MARC::File::USMARC::BEGIN@12 # spent 45µs making 1 call to vars::import
133223µs2885µs
# spent 811µs (365+446) within MARC::File::USMARC::BEGIN@13 which was called: # once (365µs+446µs) by MARC::Record::as_usmarc at line 13
use MARC::File::Encode qw( marc_to_utf8 );
# spent 811µs making 1 call to MARC::File::USMARC::BEGIN@13 # spent 74µs making 1 call to Exporter::import
14
15343µs113µs
# spent 13µs within MARC::File::USMARC::BEGIN@15 which was called: # once (13µs+0s) by MARC::Record::as_usmarc at line 15
use MARC::File;
# spent 13µs making 1 call to MARC::File::USMARC::BEGIN@15
16464µs2101µs
# spent 59µs (17+42) within MARC::File::USMARC::BEGIN@16 which was called: # once (17µs+42µ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 42µs making 1 call to vars::import
17
18351µs2143µs
# spent 80µs (17+63) within MARC::File::USMARC::BEGIN@18 which was called: # once (17µs+63µs) by MARC::Record::as_usmarc at line 18
use MARC::Record qw( LEADER_LEN );
# spent 80µs making 1 call to MARC::File::USMARC::BEGIN@18 # spent 63µs making 1 call to Exporter::import
19350µs2177µs
# spent 97µs (17+80) within MARC::File::USMARC::BEGIN@19 which was called: # once (17µs+80µs) by MARC::Record::as_usmarc at line 19
use constant SUBFIELD_INDICATOR => "\x1F";
# spent 97µs making 1 call to MARC::File::USMARC::BEGIN@19 # spent 80µs making 1 call to constant::import
20346µs2152µs
# spent 83µs (14+69) within MARC::File::USMARC::BEGIN@20 which was called: # once (14µs+69µs) by MARC::Record::as_usmarc at line 20
use constant END_OF_FIELD => "\x1E";
# spent 83µs making 1 call to MARC::File::USMARC::BEGIN@20 # spent 69µs making 1 call to constant::import
21340µs2150µs
# spent 81µs (12+69) within MARC::File::USMARC::BEGIN@21 which was called: # once (12µs+69µs) by MARC::Record::as_usmarc at line 21
use constant END_OF_RECORD => "\x1D";
# spent 81µs making 1 call to MARC::File::USMARC::BEGIN@21 # spent 69µs making 1 call to constant::import
2231.49ms2136µs
# spent 75µs (14+61) within MARC::File::USMARC::BEGIN@22 which was called: # once (14µs+61µs) by MARC::Record::as_usmarc at line 22
use constant DIRECTORY_ENTRY_LEN => 12;
# spent 75µs making 1 call to MARC::File::USMARC::BEGIN@22 # spent 61µ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.38s (2.09+5.28) within MARC::File::USMARC::_build_tag_directory which was called 5000 times, avg 1.48ms/call: # 5000 times (2.09s+5.28s) by MARC::File::USMARC::encode at line 311, avg 1.48ms/call
sub _build_tag_directory {
26250000132ms my $marc = shift;
26350006.47ms $marc = shift if (ref($marc)||$marc) =~ /^MARC::File/;
# spent 6.47ms making 5000 calls to MARC::File::USMARC::CORE:match, avg 1µ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;
270500029.6ms for my $field ( $marc->fields() ) {
# spent 29.6ms making 5000 calls to MARC::Record::fields, avg 6µs/call
271 # Dump data into proper format
2724772461.71s795414.61s my $str = $field->as_usmarc;
# spent 4.61s making 79541 calls to MARC::Field::as_usmarc, avg 58µs/call
273 push( @fields, $str );
274
275 # Create directory entry
27679541265ms my $len = bytes::length( $str );
# spent 264ms making 79540 calls to bytes::length, avg 3µs/call # spent 607µs making 1 call to bytes::AUTOLOAD
277
27879541375ms my $direntry = sprintf( "%03s%04d%05d", $field->tag, $len, $dataend );
# spent 375ms 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.80s (273ms+7.52) within MARC::File::USMARC::encode which was called 5000 times, avg 1.56ms/call: # 5000 times (273ms+7.52s) by MARC::Record::as_usmarc at line 459 of MARC/Record.pm, avg 1.56ms/call
sub encode() {
30825000269ms my $marc = shift;
30950008.95ms $marc = shift if (ref($marc)||$marc) =~ /^MARC::File/;
# spent 8.95ms making 5000 calls to MARC::File::USMARC::CORE:match, avg 2µs/call
310
31150007.38s my ($fields,$directory,$reclen,$baseaddress) = _build_tag_directory($marc);
# spent 7.38s making 5000 calls to MARC::File::USMARC::_build_tag_directory, avg 1.48ms/call
312500098.4ms $marc->set_leader_lengths( $reclen, $baseaddress );
# spent 98.4ms making 5000 calls to MARC::Record::set_leader_lengths, avg 20µs/call
313
314 # Glomp it all together
315500038.1ms return join("",$marc->leader, @$directory, END_OF_FIELD, @$fields, END_OF_RECORD);
# spent 38.1ms making 5000 calls to MARC::Record::leader, avg 8µs/call
316}
31715µs1;
318
319__END__
 
# spent 15.4ms within MARC::File::USMARC::CORE:match which was called 10000 times, avg 2µs/call: # 5000 times (8.95ms+0s) by MARC::File::USMARC::encode at line 309, avg 2µs/call # 5000 times (6.47ms+0s) by MARC::File::USMARC::_build_tag_directory at line 263, avg 1µs/call
sub MARC::File::USMARC::CORE:match; # opcode