Gedcom
view release on metacpan or search on metacpan
lib/Gedcom/Item.pm view on Meta::CPAN
$self->read if $self->{file} && $self->{file} ne "*";
$self;
}
sub copy {
my $self = shift;
my $item = $self->new;
for my $key (qw(level xref tag value pointer min max gedcom)) {
$item->{$key} = $self->{$key} if exists $self->{$key}
}
$item->{items} = [ map { $_->copy } @{$self->_items} ];
$item
}
sub hash {
my $self = shift;
my $item = {};
for my $key (qw(level xref tag value pointer min max)) {
$item->{$key} = $self->{$key} if exists $self->{$key}
}
$item->{items} = [ map { $_->hash } @{$self->_items} ];
$item
}
sub read {
my $self = shift;
# $self->{fh} = FileHandle->new($self->{file})
my $fh = $self->{fh} = gensym;
open $fh, $self->{file} or die "Can't open file $self->{file}: $!\n";
# try to determine encoding
my $encoding = "unknown";
my $bom = 0;
my $line1 = <$fh>;
if ($line1 =~ /^\xEF\xBB\xBF/) {
$encoding = "utf-8";
$bom = 1;
} else {
while (<$fh>) {
if (my ($char) = /\s*1\s+CHAR\s+(.*?)\s*$/i) {
$encoding = $char =~ /utf\W*8/i ? "utf-8" : $char;
last;
}
}
}
# print "encoding is [$encoding]\n";
$self->{gedcom}->set_encoding($encoding) if $self->{gedcom};
if ($encoding eq "utf-8" && $] >= 5.8) {
binmode $fh, ":encoding(UTF-8)";
binmode STDOUT, ":encoding(UTF-8)";
binmode STDERR, ":encoding(UTF-8)";
} else {
binmode $fh;
}
# find out how big the file is
seek($fh, 0, 2);
my $size = tell $fh;
seek($fh, $bom ? 3 : 0, 0); # skip BOM
$. = 0;
# initial callback
my $callback = $self->{callback};;
my $title = "Reading";
my $txt1 = "Reading $self->{file}";
my $count = 0;
return undef
if $callback &&
!$callback->($title, $txt1, "Record $count", tell $fh, $size);
$self->level($self->{grammar} ? -1 : -2);
my $if = "$self->{file}.index";
my ($gf, $gc);
if ($self->{gedcom}{read_only} &&
defined ($gf = -M $self->{file}) &&
defined ($gc = -M $if) && $gc < $gf) {
if (! open I, $if) {
die "Can't open $if: $!";
} else {
my $g = $self->{gedcom}{grammar}->structure("GEDCOM");
while (<I>) {
my @vals = split /\|/;
my $record =
Gedcom::Record->new(
gedcom => $self->{gedcom},
tag => $vals[0],
line => $vals[3],
cpos => $vals[4],
grammar => $g->item($vals[0]),
fh => $fh,
level => 0,
);
$record->{xref} = $vals[1] if length $vals[1];
$record->{value} = $vals[2] if length $vals[2];
my $class = $self->{gedcom}{types}{$vals[0]};
bless $record, "Gedcom::$class" if $class;
push @{$self->{items}}, $record;
}
close I or warn "Can't close $if";
}
}
unless (@{$self->{items}}) {
# $#{$self->{items}} = 20000;
# $#{$self->{items}} = -1;
# If we have a grammar, then we are reading a GEDCOM file and must use
# the grammar to verify what is being read.
# If we do not have a grammar, then that is what we are reading.
while (my $item = $self->next_item($self)) {
if ($self->{grammar}) {
my $tag = $item->{tag};
my @g = $self->{grammar}->item($tag);
# print "<$tag> => <@g>\n";
if (@g) {
$self->parse($item, $g[0]);
push @{$self->{items}}, $item;
$count++;
} else {
( run in 0.683 second using v1.01-cache-2.11-cpan-39bf76dae61 )