Filename | /usr/share/perl5/MARC/Field.pm |
Statements | Executed 2817879 statements in 9.15s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
79541 | 2 | 1 | 3.26s | 3.88s | new | MARC::Field::
79541 | 1 | 1 | 2.12s | 4.63s | as_usmarc | MARC::Field::
119082 | 1 | 1 | 1.32s | 1.84s | indicator | MARC::Field::
218623 | 3 | 1 | 976ms | 976ms | is_control_field | MARC::Field::
278164 | 3 | 1 | 607ms | 620ms | CORE:match (opcode) | MARC::Field::
79541 | 1 | 1 | 388ms | 388ms | tag | MARC::Field::
20000 | 1 | 1 | 220ms | 306ms | data | MARC::Field::
1 | 1 | 1 | 1.46ms | 1.55ms | BEGIN@5 | MARC::Field::
1 | 1 | 1 | 1.10ms | 1.61ms | BEGIN@7 | MARC::Field::
1 | 1 | 1 | 22µs | 27µs | BEGIN@3 | MARC::Field::
1 | 1 | 1 | 15µs | 19µs | BEGIN@4 | MARC::Field::
1 | 1 | 1 | 14µs | 76µs | BEGIN@8 | MARC::Field::
1 | 1 | 1 | 14µs | 54µs | BEGIN@10 | MARC::Field::
0 | 0 | 0 | 0s | 0s | _gripe | MARC::Field::
0 | 0 | 0 | 0s | 0s | _normalize_arrayref | MARC::Field::
0 | 0 | 0 | 0s | 0s | _warn | MARC::Field::
0 | 0 | 0 | 0s | 0s | add_subfields | MARC::Field::
0 | 0 | 0 | 0s | 0s | as_formatted | MARC::Field::
0 | 0 | 0 | 0s | 0s | as_string | MARC::Field::
0 | 0 | 0 | 0s | 0s | clone | MARC::Field::
0 | 0 | 0 | 0s | 0s | delete_subfield | MARC::Field::
0 | 0 | 0 | 0s | 0s | delete_subfields | MARC::Field::
0 | 0 | 0 | 0s | 0s | replace_with | MARC::Field::
0 | 0 | 0 | 0s | 0s | subfield | MARC::Field::
0 | 0 | 0 | 0s | 0s | subfields | MARC::Field::
0 | 0 | 0 | 0s | 0s | update | MARC::Field::
0 | 0 | 0 | 0s | 0s | warnings | MARC::Field::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package MARC::Field; | ||||
2 | |||||
3 | 3 | 40µs | 2 | 32µs | # spent 27µs (22+5) within MARC::Field::BEGIN@3 which was called:
# once (22µs+5µs) by MARC::Record::BEGIN@14 at line 3 # spent 27µs making 1 call to MARC::Field::BEGIN@3
# spent 5µs making 1 call to strict::import |
4 | 3 | 36µs | 2 | 23µs | # spent 19µs (15+4) within MARC::Field::BEGIN@4 which was called:
# once (15µs+4µs) by MARC::Record::BEGIN@14 at line 4 # spent 19µs making 1 call to MARC::Field::BEGIN@4
# spent 4µs making 1 call to integer::import |
5 | 3 | 583µs | 2 | 1.63ms | # spent 1.55ms (1.46+87µs) within MARC::Field::BEGIN@5 which was called:
# once (1.46ms+87µs) by MARC::Record::BEGIN@14 at line 5 # spent 1.55ms making 1 call to MARC::Field::BEGIN@5
# spent 87µs making 1 call to Exporter::import |
6 | |||||
7 | 3 | 164µs | 2 | 1.72ms | # spent 1.61ms (1.10+512µs) within MARC::Field::BEGIN@7 which was called:
# once (1.10ms+512µs) by MARC::Record::BEGIN@14 at line 7 # spent 1.61ms making 1 call to MARC::Field::BEGIN@7
# spent 111µs making 1 call to constant::import |
8 | 3 | 45µs | 2 | 138µs | # spent 76µs (14+62) within MARC::Field::BEGIN@8 which was called:
# once (14µs+62µs) by MARC::Record::BEGIN@14 at line 8 # spent 76µs making 1 call to MARC::Field::BEGIN@8
# spent 62µs making 1 call to constant::import |
9 | |||||
10 | 3 | 2.23ms | 2 | 94µs | # spent 54µs (14+40) within MARC::Field::BEGIN@10 which was called:
# once (14µs+40µs) by MARC::Record::BEGIN@14 at line 10 # spent 54µs making 1 call to MARC::Field::BEGIN@10
# spent 40µs making 1 call to vars::import |
11 | |||||
12 | =head1 NAME | ||||
13 | |||||
- - | |||||
56 | # spent 3.88s (3.26+620ms) within MARC::Field::new which was called 79541 times, avg 49µs/call:
# 59541 times (2.80s+511ms) by MARC::File::SAX::end_element at line 92 of MARC/File/SAX.pm, avg 56µs/call
# 20000 times (457ms+110ms) by MARC::File::SAX::end_element at line 83 of MARC/File/SAX.pm, avg 28µs/call | ||||
57 | 1172197 | 3.96s | my $class = shift; | ||
58 | $class = $class; | ||||
59 | |||||
60 | ## MARC spec indicates that tags can have alphabetical | ||||
61 | ## characters in them! If they do appear we assume that | ||||
62 | ## they have indicators like tags > 010 | ||||
63 | my $tagno = shift; | ||||
64 | 79541 | 232ms | ($tagno =~ /^[0-9A-Za-z]{3}$/) # spent 232ms making 79541 calls to MARC::Field::CORE:match, avg 3µs/call | ||
65 | or croak( "Tag \"$tagno\" is not a valid tag." ); | ||||
66 | 3 | 298µs | 79542 | 166ms | my $is_control = (($tagno =~ /^\d+$/) && ($tagno < 10)); # spent 164ms making 79541 calls to MARC::Field::CORE:match, avg 2µs/call
# spent 2.39ms making 1 call to utf8::AUTOLOAD |
67 | |||||
68 | my $self = bless { | ||||
69 | _tag => $tagno, | ||||
70 | _warnings => [], | ||||
71 | _is_control_field => $is_control, | ||||
72 | }, $class; | ||||
73 | |||||
74 | if ( $is_control ) { | ||||
75 | $self->{_data} = shift; | ||||
76 | } else { | ||||
77 | for my $indcode ( qw( _ind1 _ind2 ) ) { | ||||
78 | my $indicator = shift; | ||||
79 | 119082 | 224ms | if ( $indicator !~ /^[0-9A-Za-z ]$/ ) { # spent 224ms making 119082 calls to MARC::Field::CORE:match, avg 2µs/call | ||
80 | $self->_warn( "Invalid indicator \"$indicator\" forced to blank" ) unless ($indicator eq ""); | ||||
81 | $indicator = " "; | ||||
82 | } | ||||
83 | $self->{$indcode} = $indicator; | ||||
84 | } # for | ||||
85 | |||||
86 | (@_ >= 2) | ||||
87 | or croak( "Field $tagno must have at least one subfield" ); | ||||
88 | |||||
89 | # Normally, we go thru add_subfields(), but internally we can cheat | ||||
90 | $self->{_subfields} = [@_]; | ||||
91 | } | ||||
92 | |||||
93 | return $self; | ||||
94 | } # new() | ||||
95 | |||||
96 | |||||
97 | =head2 tag() | ||||
98 | |||||
- - | |||||
103 | # spent 388ms within MARC::Field::tag which was called 79541 times, avg 5µs/call:
# 79541 times (388ms+0s) by MARC::File::USMARC::_build_tag_directory at line 278 of MARC/File/USMARC.pm, avg 5µs/call | ||||
104 | 159082 | 478ms | my $self = shift; | ||
105 | return $self->{_tag}; | ||||
106 | } | ||||
107 | |||||
108 | =head2 indicator(indno) | ||||
109 | |||||
- - | |||||
116 | # spent 1.84s (1.32+524ms) within MARC::Field::indicator which was called 119082 times, avg 15µs/call:
# 119082 times (1.32s+524ms) by MARC::Field::as_usmarc at line 522, avg 15µs/call | ||||
117 | 476328 | 1.24s | my $self = shift; | ||
118 | my $indno = shift; | ||||
119 | |||||
120 | 119082 | 524ms | $self->_warn( "Fields below 010 do not have indicators" ) # spent 524ms making 119082 calls to MARC::Field::is_control_field, avg 4µs/call | ||
121 | if $self->is_control_field; | ||||
122 | |||||
123 | if ( $indno == 1 ) { | ||||
124 | return $self->{_ind1}; | ||||
125 | } elsif ( $indno == 2 ) { | ||||
126 | return $self->{_ind2}; | ||||
127 | } else { | ||||
128 | croak( "Indicator number must be 1 or 2" ); | ||||
129 | } | ||||
130 | } | ||||
131 | |||||
132 | =head2 is_control_field() | ||||
133 | |||||
- - | |||||
138 | # spent 976ms within MARC::Field::is_control_field which was called 218623 times, avg 4µs/call:
# 119082 times (524ms+0s) by MARC::Field::indicator at line 120, avg 4µs/call
# 79541 times (365ms+0s) by MARC::Field::as_usmarc at line 512, avg 5µs/call
# 20000 times (86.5ms+0s) by MARC::Field::data at line 220, avg 4µs/call | ||||
139 | 437246 | 1.28s | my $self = shift; | ||
140 | return $self->{_is_control_field}; | ||||
141 | } | ||||
142 | |||||
143 | =head2 subfield(code) | ||||
144 | |||||
- - | |||||
163 | sub subfield { | ||||
164 | my $self = shift; | ||||
165 | my $code_wanted = shift; | ||||
166 | |||||
167 | croak( "Fields below 010 do not have subfields, use data()" ) | ||||
168 | if $self->is_control_field; | ||||
169 | |||||
170 | my @data = @{$self->{_subfields}}; | ||||
171 | my @found; | ||||
172 | while ( defined( my $code = shift @data ) ) { | ||||
173 | if ( $code eq $code_wanted ) { | ||||
174 | push( @found, shift @data ); | ||||
175 | } else { | ||||
176 | shift @data; | ||||
177 | } | ||||
178 | } | ||||
179 | if ( wantarray() ) { return @found; } | ||||
180 | return( $found[0] ); | ||||
181 | } | ||||
182 | |||||
183 | =head2 subfields() | ||||
184 | |||||
- - | |||||
197 | sub subfields { | ||||
198 | my $self = shift; | ||||
199 | |||||
200 | $self->_warn( "Fields below 010 do not have subfields" ) | ||||
201 | if $self->is_control_field; | ||||
202 | |||||
203 | my @list; | ||||
204 | my @data = @{$self->{_subfields}}; | ||||
205 | while ( defined( my $code = shift @data ) ) { | ||||
206 | push( @list, [$code, shift @data] ); | ||||
207 | } | ||||
208 | return @list; | ||||
209 | } | ||||
210 | |||||
211 | =head2 data() | ||||
212 | |||||
- - | |||||
217 | # spent 306ms (220+86.5) within MARC::Field::data which was called 20000 times, avg 15µs/call:
# 20000 times (220ms+86.5ms) by MARC::Field::as_usmarc at line 512, avg 15µs/call | ||||
218 | 80000 | 207ms | my $self = shift; | ||
219 | |||||
220 | 20000 | 86.5ms | croak( "data() is only for tags less than 010, use subfield()" ) # spent 86.5ms making 20000 calls to MARC::Field::is_control_field, avg 4µs/call | ||
221 | unless $self->is_control_field; | ||||
222 | |||||
223 | $self->{_data} = $_[0] if @_; | ||||
224 | |||||
225 | return $self->{_data}; | ||||
226 | } | ||||
227 | |||||
228 | =head2 add_subfields(code,text[,code,text ...]) | ||||
229 | |||||
- - | |||||
238 | sub add_subfields { | ||||
239 | my $self = shift; | ||||
240 | |||||
241 | croak( "Subfields are only for tags >= 10" ) | ||||
242 | if $self->is_control_field; | ||||
243 | |||||
244 | push( @{$self->{_subfields}}, @_ ); | ||||
245 | return @_/2; | ||||
246 | } | ||||
247 | |||||
248 | =head2 delete_subfield() | ||||
249 | |||||
- - | |||||
274 | sub delete_subfield { | ||||
275 | my ($self, %options) = @_; | ||||
276 | my $codes = _normalize_arrayref($options{code}); | ||||
277 | my $positions = _normalize_arrayref($options{'pos'}); | ||||
278 | my $match = $options{match}; | ||||
279 | |||||
280 | croak 'match must be a compiled regex' | ||||
281 | if $match and ref($match) ne 'Regexp'; | ||||
282 | |||||
283 | my @current_subfields = @{$self->{_subfields}}; | ||||
284 | my @new_subfields = (); | ||||
285 | my $removed = 0; | ||||
286 | my $subfield_num = $[ - 1; # users $[ preferences control indexing | ||||
287 | |||||
288 | while (@current_subfields > 0) { | ||||
289 | $subfield_num += 1; | ||||
290 | my $subfield_code = shift @current_subfields; | ||||
291 | my $subfield_value = shift @current_subfields; | ||||
292 | if ((@$codes==0 or grep {$_ eq $subfield_code} @$codes) | ||||
293 | and (!$match or $subfield_value =~ $match) | ||||
294 | and (@$positions==0 or grep {$_ == $subfield_num} @$positions)) { | ||||
295 | $removed += 1; | ||||
296 | next; | ||||
297 | } | ||||
298 | push( @new_subfields, $subfield_code, $subfield_value); | ||||
299 | } | ||||
300 | $self->{_subfields} = \@new_subfields; | ||||
301 | return $removed; | ||||
302 | } | ||||
303 | |||||
304 | =head2 delete_subfields() | ||||
305 | |||||
- - | |||||
311 | sub delete_subfields { | ||||
312 | my ($self, $code) = @_; | ||||
313 | return $self->delete_subfield(code => $code); | ||||
314 | } | ||||
315 | |||||
316 | =head2 update() | ||||
317 | |||||
- - | |||||
347 | sub update { | ||||
348 | my $self = shift; | ||||
349 | |||||
350 | ## tags 000 - 009 don't have indicators or subfields | ||||
351 | if ( $self->is_control_field ) { | ||||
352 | $self->{_data} = shift; | ||||
353 | return(1); | ||||
354 | } | ||||
355 | |||||
356 | ## otherwise we need to update subfields and indicators | ||||
357 | my @data = @{$self->{_subfields}}; | ||||
358 | my $changes = 0; | ||||
359 | |||||
360 | while ( @_ ) { | ||||
361 | |||||
362 | my $arg = shift; | ||||
363 | my $val = shift; | ||||
364 | |||||
365 | ## indicator update | ||||
366 | if ($arg =~ /^ind[12]$/) { | ||||
367 | $self->{"_$arg"} = $val; | ||||
368 | $changes++; | ||||
369 | } | ||||
370 | |||||
371 | ## subfield update | ||||
372 | else { | ||||
373 | my $found = 0; | ||||
374 | ## update existing subfield | ||||
375 | for ( my $i=0; $i<@data; $i+=2 ) { | ||||
376 | if ($data[$i] eq $arg) { | ||||
377 | $data[$i+1] = $val; | ||||
378 | $found = 1; | ||||
379 | $changes++; | ||||
380 | last; | ||||
381 | } | ||||
382 | } # for | ||||
383 | |||||
384 | ## append new subfield | ||||
385 | if ( !$found ) { | ||||
386 | push( @data, $arg, $val ); | ||||
387 | $changes++; | ||||
388 | } | ||||
389 | } | ||||
390 | |||||
391 | } # while | ||||
392 | |||||
393 | ## synchronize our subfields | ||||
394 | $self->{_subfields} = \@data; | ||||
395 | return($changes); | ||||
396 | |||||
397 | } | ||||
398 | |||||
399 | =head2 replace_with() | ||||
400 | |||||
- - | |||||
413 | sub replace_with { | ||||
414 | |||||
415 | my ($self,$new) = @_; | ||||
416 | ref($new) =~ /^MARC::Field$/ | ||||
417 | or croak("Must pass a MARC::Field object"); | ||||
418 | |||||
419 | %$self = %$new; | ||||
420 | |||||
421 | } | ||||
422 | |||||
423 | |||||
424 | =head2 as_string( [$subfields] ) | ||||
425 | |||||
- - | |||||
449 | sub as_string() { | ||||
450 | my $self = shift; | ||||
451 | my $subfields = shift; | ||||
452 | |||||
453 | if ( $self->is_control_field ) { | ||||
454 | return $self->{_data}; | ||||
455 | } | ||||
456 | |||||
457 | my @subs; | ||||
458 | |||||
459 | my $subs = $self->{_subfields}; | ||||
460 | my $nfields = @$subs / 2; | ||||
461 | for my $i ( 1..$nfields ) { | ||||
462 | my $offset = ($i-1)*2; | ||||
463 | my $code = $subs->[$offset]; | ||||
464 | my $text = $subs->[$offset+1]; | ||||
465 | push( @subs, $text ) if !$subfields || $code =~ /^[$subfields]$/; | ||||
466 | } # for | ||||
467 | |||||
468 | return join( " ", @subs ); | ||||
469 | } | ||||
470 | |||||
471 | |||||
472 | =head2 as_formatted() | ||||
473 | |||||
- - | |||||
478 | sub as_formatted() { | ||||
479 | my $self = shift; | ||||
480 | |||||
481 | my @lines; | ||||
482 | |||||
483 | if ( $self->is_control_field ) { | ||||
484 | push( @lines, sprintf( "%03s %s", $self->{_tag}, $self->{_data} ) ); | ||||
485 | } else { | ||||
486 | my $hanger = sprintf( "%03s %1.1s%1.1s", $self->{_tag}, $self->{_ind1}, $self->{_ind2} ); | ||||
487 | |||||
488 | my $subs = $self->{_subfields}; | ||||
489 | my $nfields = @$subs / 2; | ||||
490 | my $offset = 0; | ||||
491 | for my $i ( 1..$nfields ) { | ||||
492 | push( @lines, sprintf( "%-6.6s _%1.1s%s", $hanger, $subs->[$offset++], $subs->[$offset++] ) ); | ||||
493 | $hanger = ""; | ||||
494 | } # for | ||||
495 | } | ||||
496 | |||||
497 | return join( "\n", @lines ); | ||||
498 | } | ||||
499 | |||||
500 | |||||
501 | =head2 as_usmarc() | ||||
502 | |||||
- - | |||||
508 | # spent 4.63s (2.12+2.51) within MARC::Field::as_usmarc which was called 79541 times, avg 58µs/call:
# 79541 times (2.12s+2.51s) by MARC::File::USMARC::_build_tag_directory at line 272 of MARC/File/USMARC.pm, avg 58µs/call | ||||
509 | 493004 | 1.99s | my $self = shift; | ||
510 | |||||
511 | # Tags < 010 are pretty easy | ||||
512 | 99541 | 671ms | if ( $self->is_control_field ) { # spent 365ms making 79541 calls to MARC::Field::is_control_field, avg 5µs/call
# spent 306ms making 20000 calls to MARC::Field::data, avg 15µs/call | ||
513 | return $self->data . END_OF_FIELD; | ||||
514 | } else { | ||||
515 | my @subs; | ||||
516 | my @subdata = @{$self->{_subfields}}; | ||||
517 | while ( @subdata ) { | ||||
518 | push( @subs, join( "", SUBFIELD_INDICATOR, shift @subdata, shift @subdata ) ); | ||||
519 | } # while | ||||
520 | |||||
521 | return | ||||
522 | 119082 | 1.84s | join( "", # spent 1.84s making 119082 calls to MARC::Field::indicator, avg 15µs/call | ||
523 | $self->indicator(1), | ||||
524 | $self->indicator(2), | ||||
525 | @subs, | ||||
526 | END_OF_FIELD, ); | ||||
527 | } | ||||
528 | } | ||||
529 | |||||
530 | =head2 clone() | ||||
531 | |||||
- - | |||||
544 | sub clone { | ||||
545 | my $self = shift; | ||||
546 | |||||
547 | my $tagno = $self->{_tag}; | ||||
548 | my $is_control = (($tagno =~ /^\d+$/) && ($tagno < 10)); | ||||
549 | |||||
550 | my $clone = | ||||
551 | bless { | ||||
552 | _tag => $tagno, | ||||
553 | _warnings => [], | ||||
554 | _is_control_field => $is_control, | ||||
555 | }, ref($self); | ||||
556 | |||||
557 | if ( $is_control ) { | ||||
558 | $clone->{_data} = $self->{_data}; | ||||
559 | } else { | ||||
560 | $clone->{_ind1} = $self->{_ind1}; | ||||
561 | $clone->{_ind2} = $self->{_ind2}; | ||||
562 | $clone->{_subfields} = [@{$self->{_subfields}}]; | ||||
563 | } | ||||
564 | |||||
565 | return $clone; | ||||
566 | } | ||||
567 | |||||
568 | =head2 warnings() | ||||
569 | |||||
- - | |||||
579 | sub warnings() { | ||||
580 | my $self = shift; | ||||
581 | |||||
582 | return @{$self->{_warnings}}; | ||||
583 | } | ||||
584 | |||||
585 | # NOTE: _warn is an object method | ||||
586 | sub _warn($) { | ||||
587 | my $self = shift; | ||||
588 | |||||
589 | push( @{$self->{_warnings}}, join( "", @_ ) ); | ||||
590 | } | ||||
591 | |||||
592 | sub _gripe(@) { | ||||
593 | $ERROR = join( "", @_ ); | ||||
594 | |||||
595 | warn $ERROR; | ||||
596 | |||||
597 | return; | ||||
598 | } | ||||
599 | |||||
600 | sub _normalize_arrayref { | ||||
601 | my $ref = shift; | ||||
602 | if (ref($ref) eq 'ARRAY') { return $ref } | ||||
603 | elsif (defined $ref) { return [$ref] } | ||||
604 | return []; | ||||
605 | } | ||||
606 | |||||
607 | |||||
608 | 1 | 4µs | 1; | ||
609 | |||||
610 | __END__ | ||||
# spent 620ms (607+13.5) within MARC::Field::CORE:match which was called 278164 times, avg 2µs/call:
# 119082 times (224ms+0s) by MARC::Field::new at line 79, avg 2µs/call
# 79541 times (232ms+0s) by MARC::Field::new at line 64, avg 3µs/call
# 79541 times (150ms+13.5ms) by MARC::Field::new at line 66, avg 2µs/call |