The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use Storable qw(nstore_fd fd_retrieve);
use Treex::PML::IO qw( close_backend);
use strict;
use vars qw($VERSION);
BEGIN {
$VERSION='2.05'; # version template
}
use Scalar::Util qw(blessed reftype refaddr);
sub test {
my ($f,$encoding)=@_;
if (ref($f)) {
return $f->getline()=~/^pst0/;
} else {
my $fh = open_backend($f,"r");
my $test = $fh && test($fh,$encoding);
close_backend($fh);
return $test;
}
}
sub open_backend {
Treex::PML::IO::open_backend(@_[0,1]);
}
sub read {
my ($fd,$fs)=@_;
binmode($fd);
my $restore = fd_retrieve($fd);
my $api_version = $restore->[6];
unless ($Treex::PML::COMPATIBLE_API_VERSION{ $api_version }) {
$api_version='0.001' unless defined $api_version;
warn "Warning: the binary file ".$fs->filename." is a dump of structures created by possibly incompatible Treex::PML API version $api_version (the current Treex::PML API version is $Treex::PML::API_VERSION)\n";
}
# support for old Fslib-based documents:
if (ref($restore->[0]) eq 'FSFormat' and not defined($Fslib::VERSION)) {
# upgrade to Treex::PML
# warn "Warning: Detected Fslib-based file and Fslib is not loaded: upgrading to Treex::PML!\n";
upgrade_from_fslib($restore);
}
$fs->changeTail(@{$restore->[2]});
$fs->[13]=$restore->[3]; # metaData
my $appData = delete $fs->[13]->{'StorableBackend:savedAppData'};
if ($appData) {
$fs->changeAppData($_,$appData->{$_}) foreach keys(%$appData);
}
$fs->changePatterns(@{$restore->[4]});
$fs->changeHint($restore->[5]);
# place to update some internal stuff if necessary
my $schema = $fs->metaData('schema');
if (ref($schema) and !$schema->{-api_version}) {
$schema->convert_from_hash();
$schema->post_process();
}
$fs->changeFS($restore->[0]);
$fs->changeTrees(@{$restore->[1]});
$fs->FS->renew_specials();
# $fs->_weakenLinks;
}
sub write {
my ($fd,$fs)=@_;
binmode($fd);
my $metaData = { %{$fs->[13]} };
my $ref = $fs->appData('ref');
$metaData->{'StorableBackend:savedAppData'}||={};
foreach my $savedAppData ($metaData->{'StorableBackend:savedAppData'}) {
$savedAppData->{'id-hash'} = $fs->appData('id-hash');
$savedAppData->{'ref'} = {
map {
my $val = $ref->{$_};
UNIVERSAL::DOES::does($val,'Treex::PML::Instance') ? ($_ => $val) : ()
} keys %$ref
} if ref $ref;
}
nstore_fd([$fs->FS,
$fs->treeList,
[$fs->tail],
$metaData,
[$fs->patterns],
$fs->hint,
$Treex::PML::API_VERSION
],$fd);
}
sub upgrade_from_fslib {
my @next = @_;
my %seen;
$seen{refaddr($_)}=1 for @next;
while (@next) {
my $object = shift @next;
my $ref = ref($object);
next unless $ref;
my $is = blessed($object);
if (defined $is) {
if ($is =~ /^Treex/) {
} elsif ($is eq 'FSNode') {
bless $object, 'Treex::PML::Node';
} elsif ($is eq 'Fslib::Type') {
bless $object, 'Treex::PML::Backend::Storable::CopmpatType';
} elsif ($is =~ /^Fslib::(.*)$/) {
bless $object, qq{Treex::PML::$1};
} elsif ($is =~ /^PMLSchema(::.*)?$/) {
bless $object, qq{Treex::PML::Schema$1};
} elsif ($is eq 'FSFile') {
bless $object, 'Treex::PML::Document';
} elsif ($is eq 'FSFormat') {
bless $object, 'Treex::PML::FSFormat';
} elsif ($is eq 'PMLInstance') {
bless $object, 'Treex::PML::Instance';
}
$ref = reftype($object);
}
for (($ref eq 'HASH') ? values(%$object)
: ($ref eq 'ARRAY') ? @$object
: ($ref eq 'SCALAR') ? $$object : ()) {
my $key = refaddr($_) || next;
push @next, $_ unless ($seen{$key}++);
}
}
}
use Carp;
use strict;
use vars qw($AUTOLOAD);
# This is handler for obsoleted class 'Fslib::Type'
# which has no API-compatible counterpart in Treex::PML.
# The object is a pair (ARRAYref) containing PML schema and type declaration.
sub schema {
my ($self)=@_;
return $self->[0];
}
sub type_decl {
my ($self)=@_;
return $self->[1];
}
# delegate every method to the type
sub AUTOLOAD {
my $self = shift;
croak "$self is not an object" unless ref($self);
my $name = $AUTOLOAD;
$name =~ s/.*://; # strip fully-qualified portion
return $self->[1]->$name(@_);
}
1;
__END__
=pod
=head1 NAME
Treex::PML::Backend::Storable - I/O backend for data dumps via the Perl Storable module.
=head1 DESCRIPTION
This module implements a Treex::PML input/output backend for binary
dumps of the in-memory representation of Treex::PML::Document objects
using the Perl module Storable.
=head1 SYNOPSIS
use Treex::PML;
Treex::PML::AddBackends(qw(Storable))
my $document = Treex::PML::Factory->createDocumentFromFile('input.pls');
...
$document->save();
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2006-2010 by Petr Pajas
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.2 or,
at your option, any later version of Perl 5 you may have available.
=cut