added to_hash, small fix to test, better output in dump_fastmarc.pl [0.02]
authorDobrica Pavlinusic <dpavlin@rot13.org>
Sun, 18 Dec 2005 23:12:26 +0000 (23:12 +0000)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Sun, 18 Dec 2005 23:12:26 +0000 (23:12 +0000)
git-svn-id: svn+ssh://llin/home/dpavlin/private/svn/MARC-Fast/trunk@6 49f9634a-d7ec-0310-8e6b-ec35c6cc8804

Fast.pm
META.yml
scripts/dump_fastmarc.pl
t/001_marc.t

diff --git a/Fast.pm b/Fast.pm
index 9a981be..6116b14 100644 (file)
--- a/Fast.pm
+++ b/Fast.pm
@@ -59,6 +59,7 @@ sub new {
        print STDERR "# opening ",$self->{marcdb},"\n" if ($self->{debug});
 
        open($self->{fh}, $self->{marcdb}) || croak "can't open ",$self->{marcdb},": $!";
+       binmode($self->{fh});
 
        $self->{count} = 0;
 
@@ -69,7 +70,12 @@ sub new {
                push @{$self->{fh_offset}}, tell($self->{fh});
 
                my $leader;
-               read($self->{fh}, $leader, 24);
+               my $len = read($self->{fh}, $leader, 24);
+
+               if ($len < 24) {
+                       carp "short read of leader, aborting\n";
+                       last;
+               }
 
                # Byte        Name
                # ----        ----
@@ -103,7 +109,12 @@ sub new {
                push @{$self->{leaders}}, $leader;
 
                # skip to next record
-               seek($self->{fh},substr($leader,0,5)-24,1);
+               my $o = substr($leader,0,5);
+               if ($o > 24) {
+                       seek($self->{fh},$o-24,1) if ($o);
+               } else {
+                       last;
+               }
 
        }
 
@@ -196,11 +207,7 @@ sub fetch {
                my $f = substr($fields,$addr,$len);
                print STDERR "tag/len/addr $tag [$len] $addr: '$f'\n" if ($self->{debug});
 
-               if ($row->{$tag}) {
-                       $row->{$tag} .= $f;
-               } else {
-                       $row->{$tag} = $f;
-               }
+               push @{ $row->{$tag} }, $f;
 
                my $del = substr($fields,$addr+$len-1,1);
 
@@ -221,6 +228,75 @@ sub fetch {
        return $row;
 }
 
+
+=head2 to_hash
+
+Read record with specified MFN and convert it to hash
+
+  my $hash = $marc->to_hash($mfn);
+
+It has ability to convert characters (using C<hash_filter>) from MARC
+database before creating structures enabling character re-mapping or quick
+fix-up of data.
+
+This function returns hash which is like this:
+
+  '200' => [
+             {
+               'i1' => '1',
+               'i2' => ' '
+               'a' => 'Goa',
+               'f' => 'Valdo D\'Arienzo',
+               'e' => 'tipografie e tipografi nel XVI secolo',
+             }
+           ],
+
+This method will also create additional field C<000> with MFN.
+
+=cut
+
+sub to_hash {
+       my $self = shift;
+
+       my $mfn = shift || confess "need mfn!";
+
+       # init record to include MFN as field 000
+       my $rec = { '000' => [ $mfn ] };
+
+       my $row = $self->fetch($mfn) || return;
+
+       foreach my $k (keys %{$row}) {
+               foreach my $l (@{$row->{$k}}) {
+
+                       # remove end marker
+                       $l =~ s/\x1E$//;
+
+                       # filter output
+                       $l = $self->{'hash_filter'}->($l) if ($self->{'hash_filter'});
+
+                       my $val;
+
+                       # has identifiers?
+                       ($val->{'i1'},$val->{'i2'}) = ($1,$2) if ($l =~ s/^([01 #])([01 #])\x1F/\x1F/);
+
+                       # has subfields?
+                       if ($l =~ m/\x1F/) {
+                               foreach my $t (split(/\x1F/,$l)) {
+                                       next if (! $t);
+                                       $val->{substr($t,0,1)} = substr($t,1);
+                               }
+                       } else {
+                               $val = $l;
+                       }
+
+                       push @{$rec->{$k}}, $val;
+               }
+       }
+
+       return $rec;
+}
+
+
 1;
 __END__
 
index 9a928f9..468eebc 100644 (file)
--- a/META.yml
+++ b/META.yml
@@ -1,7 +1,7 @@
 # http://module-build.sourceforge.net/META-spec.html
 #XXXXXXX This is a prototype!!!  It will change in the future!!! XXXXX#
 name:         MARC-Fast
-version:      0.01
+version:      0.02
 version_from: Fast.pm
 installdirs:  site
 requires:
index a37171c..538f8ea 100755 (executable)
@@ -17,22 +17,24 @@ my $marc = new MARC::Fast(
        debug => $opt{'d'},
 );
 
-print STDERR "$file has ",$marc->count," records...\n";
 
 my $min = 1;
 my $max = $marc->count;
 
 if (my $mfn = $opt{'n'}) {
        $min = $max = $mfn;
+       print STDERR "Dumping $mfn only\n";
+} else {
+       print STDERR "$file has $max records...\n";
 }
 
-print STDERR "Dumping $min - $max\n" if ($opt{'d'});
-
 for my $mfn ($min .. $max) {
        my $rec = $marc->fetch($mfn) || next;
+       print Dumper($rec);
        print "REC $mfn\n";
        foreach my $f (sort keys %{$rec}) {
-               print "$f\t",$rec->{$f},"\n";
+               print "$f\t", join('', $rec->{$f}) ,"\n";
        }
        print "\n";
+       print Dumper($marc->to_hash($mfn));
 }
index 60254b5..691a3a2 100755 (executable)
@@ -21,7 +21,7 @@ throws_ok { $marc = MARC::Fast->new(%param); } qr/foo.bar/, "marcdb exist";
 $param{marcdb} = 'data/unimarc.iso';
 
 SKIP: {
-       skip "no ",$param{marcdb}," test file ", 18 unless (-e $param{marcdb});
+       skip "no $param{marcdb} test file ", 17 unless (-e $param{marcdb});
 
        ok($marc = MARC::Fast->new(%param), "new");