Filename | /usr/share/perl5/MARC/Field.pm |
Statements | Executed 2817879 statements in 8.91s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
79541 | 2 | 1 | 3.12s | 3.68s | new | MARC::Field::
79541 | 1 | 1 | 2.10s | 4.61s | as_usmarc | MARC::Field::
119082 | 1 | 1 | 1.31s | 1.84s | indicator | MARC::Field::
218623 | 3 | 1 | 977ms | 977ms | is_control_field | MARC::Field::
278164 | 3 | 1 | 548ms | 561ms | CORE:match (opcode) | MARC::Field::
79541 | 1 | 1 | 375ms | 375ms | tag | MARC::Field::
20000 | 1 | 1 | 223ms | 310ms | data | MARC::Field::
1 | 1 | 1 | 1.53ms | 1.61ms | BEGIN@5 | MARC::Field::
1 | 1 | 1 | 1.10ms | 1.67ms | BEGIN@7 | MARC::Field::
1 | 1 | 1 | 22µs | 28µs | BEGIN@3 | MARC::Field::
1 | 1 | 1 | 16µs | 19µs | BEGIN@4 | MARC::Field::
1 | 1 | 1 | 14µs | 50µs | BEGIN@10 | MARC::Field::
1 | 1 | 1 | 14µs | 78µs | BEGIN@8 | 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 | 49µs | 2 | 34µs | # spent 28µs (22+6) within MARC::Field::BEGIN@3 which was called:
# once (22µs+6µs) by MARC::Record::BEGIN@14 at line 3 # spent 28µs making 1 call to MARC::Field::BEGIN@3
# spent 6µs making 1 call to strict::import |
4 | 3 | 37µs | 2 | 22µs | # spent 19µs (16+3) within MARC::Field::BEGIN@4 which was called:
# once (16µs+3µs) by MARC::Record::BEGIN@14 at line 4 # spent 19µs making 1 call to MARC::Field::BEGIN@4
# spent 3µs making 1 call to integer::import |
5 | 3 | 577µs | 2 | 1.70ms | # spent 1.61ms (1.53+86µs) within MARC::Field::BEGIN@5 which was called:
# once (1.53ms+86µs) by MARC::Record::BEGIN@14 at line 5 # spent 1.61ms making 1 call to MARC::Field::BEGIN@5
# spent 86µs making 1 call to Exporter::import |
6 | |||||
7 | 3 | 166µs | 2 | 1.83ms | # spent 1.67ms (1.10+570µs) within MARC::Field::BEGIN@7 which was called:
# once (1.10ms+570µs) by MARC::Record::BEGIN@14 at line 7 # spent 1.67ms making 1 call to MARC::Field::BEGIN@7
# spent 160µs making 1 call to constant::import |
8 | 3 | 52µs | 2 | 142µs | # spent 78µs (14+64) within MARC::Field::BEGIN@8 which was called:
# once (14µs+64µs) by MARC::Record::BEGIN@14 at line 8 # spent 78µs making 1 call to MARC::Field::BEGIN@8
# spent 64µs making 1 call to constant::import |
9 | |||||
10 | 3 | 2.38ms | 2 | 86µs | # spent 50µs (14+36) within MARC::Field::BEGIN@10 which was called:
# once (14µs+36µs) by MARC::Record::BEGIN@14 at line 10 # spent 50µs making 1 call to MARC::Field::BEGIN@10
# spent 36µs making 1 call to vars::import |
11 | |||||
12 | =head1 NAME | ||||
13 | |||||
- - | |||||
56 | # spent 3.68s (3.12+561ms) within MARC::Field::new which was called 79541 times, avg 46µs/call:
# 59541 times (2.68s+466ms) by MARC::File::XML::decode at line 463 of lib/MARC/File/XML.pm, avg 53µs/call
# 20000 times (437ms+95.2ms) by MARC::File::XML::decode at line 449 of lib/MARC/File/XML.pm, avg 27µs/call | ||||
57 | 79541 | 116ms | my $class = shift; | ||
58 | 79541 | 78.0ms | $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 | 79541 | 88.0ms | my $tagno = shift; | ||
64 | 79541 | 506ms | 79541 | 191ms | ($tagno =~ /^[0-9A-Za-z]{3}$/) # spent 191ms making 79541 calls to MARC::Field::CORE:match, avg 2µs/call |
65 | or croak( "Tag \"$tagno\" is not a valid tag." ); | ||||
66 | 79544 | 471ms | 79542 | 153ms | my $is_control = (($tagno =~ /^\d+$/) && ($tagno < 10)); # spent 150ms making 79541 calls to MARC::Field::CORE:match, avg 2µs/call
# spent 2.43ms making 1 call to utf8::AUTOLOAD |
67 | |||||
68 | 79541 | 358ms | my $self = bless { | ||
69 | _tag => $tagno, | ||||
70 | _warnings => [], | ||||
71 | _is_control_field => $is_control, | ||||
72 | }, $class; | ||||
73 | |||||
74 | 79541 | 165ms | if ( $is_control ) { | ||
75 | $self->{_data} = shift; | ||||
76 | } else { | ||||
77 | 59541 | 149ms | for my $indcode ( qw( _ind1 _ind2 ) ) { | ||
78 | 119082 | 142ms | my $indicator = shift; | ||
79 | 119082 | 669ms | 119082 | 219ms | if ( $indicator !~ /^[0-9A-Za-z ]$/ ) { # spent 219ms 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 | 119082 | 407ms | $self->{$indcode} = $indicator; | ||
84 | } # for | ||||
85 | |||||
86 | 59541 | 66.8ms | (@_ >= 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 | 59541 | 172ms | $self->{_subfields} = [@_]; | ||
91 | } | ||||
92 | |||||
93 | 79541 | 366ms | return $self; | ||
94 | } # new() | ||||
95 | |||||
96 | |||||
97 | =head2 tag() | ||||
98 | |||||
- - | |||||
103 | # spent 375ms within MARC::Field::tag which was called 79541 times, avg 5µs/call:
# 79541 times (375ms+0s) by MARC::File::USMARC::_build_tag_directory at line 278 of MARC/File/USMARC.pm, avg 5µs/call | ||||
104 | 79541 | 92.2ms | my $self = shift; | ||
105 | 79541 | 380ms | return $self->{_tag}; | ||
106 | } | ||||
107 | |||||
108 | =head2 indicator(indno) | ||||
109 | |||||
- - | |||||
116 | # spent 1.84s (1.31+532ms) within MARC::Field::indicator which was called 119082 times, avg 15µs/call:
# 119082 times (1.31s+532ms) by MARC::Field::as_usmarc at line 522, avg 15µs/call | ||||
117 | 119082 | 134ms | my $self = shift; | ||
118 | 119082 | 121ms | my $indno = shift; | ||
119 | |||||
120 | 119082 | 461ms | 119082 | 532ms | $self->_warn( "Fields below 010 do not have indicators" ) # spent 532ms making 119082 calls to MARC::Field::is_control_field, avg 4µs/call |
121 | if $self->is_control_field; | ||||
122 | |||||
123 | 119082 | 510ms | 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 977ms within MARC::Field::is_control_field which was called 218623 times, avg 4µs/call:
# 119082 times (532ms+0s) by MARC::Field::indicator at line 120, avg 4µs/call
# 79541 times (358ms+0s) by MARC::Field::as_usmarc at line 512, avg 5µs/call
# 20000 times (86.4ms+0s) by MARC::Field::data at line 220, avg 4µs/call | ||||
139 | 218623 | 222ms | my $self = shift; | ||
140 | 218623 | 1.06s | 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 310ms (223+86.4) within MARC::Field::data which was called 20000 times, avg 15µs/call:
# 20000 times (223ms+86.4ms) by MARC::Field::as_usmarc at line 512, avg 15µs/call | ||||
218 | 20000 | 22.6ms | my $self = shift; | ||
219 | |||||
220 | 20000 | 85.9ms | 20000 | 86.4ms | croak( "data() is only for tags less than 010, use subfield()" ) # spent 86.4ms making 20000 calls to MARC::Field::is_control_field, avg 4µs/call |
221 | unless $self->is_control_field; | ||||
222 | |||||
223 | 20000 | 20.5ms | $self->{_data} = $_[0] if @_; | ||
224 | |||||
225 | 20000 | 83.5ms | 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.61s (2.10+2.51) within MARC::Field::as_usmarc which was called 79541 times, avg 58µs/call:
# 79541 times (2.10s+2.51s) by MARC::File::USMARC::_build_tag_directory at line 272 of MARC/File/USMARC.pm, avg 58µs/call | ||||
509 | 79541 | 91.4ms | my $self = shift; | ||
510 | |||||
511 | # Tags < 010 are pretty easy | ||||
512 | 79541 | 457ms | 99541 | 668ms | if ( $self->is_control_field ) { # spent 358ms making 79541 calls to MARC::Field::is_control_field, avg 5µs/call
# spent 310ms making 20000 calls to MARC::Field::data, avg 15µs/call |
513 | return $self->data . END_OF_FIELD; | ||||
514 | } else { | ||||
515 | 59541 | 56.1ms | my @subs; | ||
516 | 59541 | 155ms | my @subdata = @{$self->{_subfields}}; | ||
517 | 59541 | 135ms | while ( @subdata ) { | ||
518 | 95758 | 330ms | push( @subs, join( "", SUBFIELD_INDICATOR, shift @subdata, shift @subdata ) ); | ||
519 | } # while | ||||
520 | |||||
521 | return | ||||
522 | 59541 | 740ms | 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 561ms (548+13.1) within MARC::Field::CORE:match which was called 278164 times, avg 2µs/call:
# 119082 times (219ms+0s) by MARC::Field::new at line 79, avg 2µs/call
# 79541 times (191ms+0s) by MARC::Field::new at line 64, avg 2µs/call
# 79541 times (137ms+13.1ms) by MARC::Field::new at line 66, avg 2µs/call |