home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / Reference.pm < prev    next >
Encoding:
Perl POD Document  |  2003-11-21  |  10.3 KB  |  358 lines

  1. # $Id: Reference.pm,v 1.28 2003/11/21 05:08:25 rcaputo Exp $
  2.  
  3. # Filter::Reference partial copyright 1998 Artur Bergman
  4. # <artur@vogon-solutions.com>.  Partial copyright 1999 Philip Gwyn.
  5.  
  6. package POE::Filter::Reference;
  7. use POE::Preprocessor ( isa => "POE::Macro::UseBytes" );
  8.  
  9. use strict;
  10.  
  11. use vars qw($VERSION);
  12. $VERSION = do {my@r=(q$Revision: 1.28 $=~/\d+/g);sprintf"%d."."%04d"x$#r,@r};
  13.  
  14. use Carp qw(carp croak);
  15.  
  16. #------------------------------------------------------------------------------
  17. # Try to require one of the default freeze/thaw packages.
  18.  
  19. sub _default_freezer {
  20.   local $SIG{'__DIE__'} = 'DEFAULT';
  21.   my $ret;
  22.  
  23.   foreach my $p (qw(Storable FreezeThaw YAML)) {
  24.     eval { require "$p.pm"; import $p (); };
  25.     warn $@ if $@;
  26.     return $p if $@ eq '';
  27.   }
  28.   die "Filter::Reference requires Storable, FreezeThaw, or YAML";
  29. }
  30.  
  31. #------------------------------------------------------------------------------
  32. # Try to acquire Compress::Zlib at runtime.
  33.  
  34. my $zlib_status = undef;
  35. sub _include_zlib {
  36.   local $SIG{'__DIE__'} = 'DEFAULT';
  37.  
  38.   unless (defined $zlib_status) {
  39.     eval { require 'Compress::Zlib';
  40.            import Compress::Zlib qw(compress uncompress);
  41.          };
  42.     if ($@) {
  43.       $zlib_status = $@;
  44.       eval <<'      EOE';
  45.         sub compress { @_ }
  46.         sub uncompress { @_ }
  47.       EOE
  48.     }
  49.     else {
  50.       $zlib_status = '';
  51.     }
  52.   }
  53.  
  54.   $zlib_status;
  55. }
  56.  
  57. #------------------------------------------------------------------------------
  58.  
  59. sub new {
  60.   my($type, $freezer, $compression) = @_;
  61.   $freezer ||= _default_freezer();
  62.  
  63.   # not a reference... maybe a package?
  64.   unless(ref $freezer) {
  65.     my $symtable=$::{"main::"};
  66.  
  67.     # find out of the package was loaded
  68.     my $loaded=1;
  69.     foreach my $p (split /::/, $freezer) {
  70.       unless(exists $symtable->{"$p\::"}) {
  71.         $loaded=0;
  72.         last;
  73.       }
  74.       $symtable=$symtable->{"$p\::"};
  75.     }
  76.  
  77.     unless($loaded) {
  78.       my $q=$freezer;
  79.       $q=~s(::)(/)g;
  80.       eval {require "$q.pm"; import $freezer ();};
  81.       croak $@ if $@;
  82.     }
  83.   }
  84.  
  85.   # Now get the methodes we want
  86.   my $freeze=$freezer->can('nfreeze') || $freezer->can('freeze');
  87.   carp "$freezer doesn't have a freeze or nfreeze method" unless $freeze;
  88.   my $thaw=$freezer->can('thaw');
  89.   carp "$freezer doesn't have a thaw method" unless $thaw;
  90.  
  91.  
  92.   # If it's an object, we use closures to create a $self->method()
  93.   my $tf=$freeze;
  94.   my $tt=$thaw;
  95.   if(ref $freezer) {
  96.     $tf=sub {$freeze->($freezer, @_)};
  97.     $tt=sub {$thaw->($freezer, @_)};
  98.   }
  99.  
  100.   # Compression
  101.   $compression ||= 0;
  102.   if ($compression) {
  103.     my $zlib_status = &_include_zlib();
  104.     if ($zlib_status ne '') {
  105.       warn "Compress::Zlib load failed with error: $zlib_status\n";
  106.       carp "Filter::Reference compression option ignored";
  107.       $compression = 0;
  108.     }
  109.   }
  110.  
  111.   my $self = bless { buffer    => '',
  112.                      expecting => undef,
  113.                      thaw      => $tt,
  114.                      freeze    => $tf,
  115.                      compress  => $compression,
  116.                    }, $type;
  117.   $self;
  118. }
  119.  
  120. #------------------------------------------------------------------------------
  121.  
  122. sub get {
  123.   my ($self, $stream) = @_;
  124.   my @return;
  125.  
  126.   {% use_bytes %}
  127.  
  128.   $self->{buffer} .= join('', @$stream);
  129.  
  130.   while ( defined($self->{expecting}) ||
  131.           ( ($self->{buffer} =~ s/^(\d+)\0//s) &&
  132.             ($self->{expecting} = $1)
  133.           )
  134.   ) {
  135.     last if (length $self->{buffer} < $self->{expecting});
  136.  
  137.     my $chunk = substr($self->{buffer}, 0, $self->{expecting});
  138.     substr($self->{buffer}, 0, $self->{expecting}) = '';
  139.     undef $self->{expecting};
  140.  
  141.     $chunk = uncompress($chunk) if $self->{compress};
  142.     push @return, $self->{thaw}->( $chunk );
  143.   }
  144.  
  145.   return \@return;
  146. }
  147.  
  148. #------------------------------------------------------------------------------
  149. # 2001-07-27 RCC: The get_one() variant of get() allows Wheel::Xyz to
  150. # retrieve one filtered block at a time.  This is necessary for filter
  151. # changing and proper input flow control.
  152.  
  153. sub get_one_start {
  154.   my ($self, $stream) = @_;
  155.   $self->{buffer} .= join('', @$stream);
  156. }
  157.  
  158. sub get_one {
  159.   my $self = shift;
  160.  
  161.   {% use_bytes %}
  162.  
  163.   while ( defined($self->{expecting}) ||
  164.           ( ($self->{buffer} =~ s/^(\d+)\0//s) &&
  165.             ($self->{expecting} = $1)
  166.           )
  167.   ) {
  168.     return [ ] if length($self->{buffer}) < $self->{expecting};
  169.  
  170.     my $chunk = substr($self->{buffer}, 0, $self->{expecting});
  171.     substr($self->{buffer}, 0, $self->{expecting}) = '';
  172.     undef $self->{expecting};
  173.  
  174.     $chunk = uncompress($chunk) if $self->{compress};
  175.     return [ $self->{thaw}->( $chunk ) ];
  176.   }
  177.  
  178.   return [ ];
  179. }
  180.  
  181. #------------------------------------------------------------------------------
  182. # freeze one or more references, and return a string representing them
  183.  
  184. sub put {
  185.   my ($self, $references) = @_;
  186.  
  187.   {% use_bytes %}
  188.  
  189.   my @raw = map {
  190.     my $frozen = $self->{freeze}->($_);
  191.     $frozen = compress($frozen) if $self->{compress};
  192.     length($frozen) . "\0" . $frozen;
  193.   } @$references;
  194.   \@raw;
  195. }
  196.  
  197. #------------------------------------------------------------------------------
  198. # Return everything we have outstanding.  Do not destroy our framing
  199. # buffer, though.
  200.  
  201. sub get_pending {
  202.   my $self = shift;
  203.   return undef unless length $self->{buffer};
  204.   return [ $self->{buffer} ];
  205. }
  206.  
  207. ###############################################################################
  208. 1;
  209.  
  210. __END__
  211.  
  212. =head1 NAME
  213.  
  214. POE::Filter::Reference - freeze data for sending; thaw data when it arrives
  215.  
  216. =head1 SYNOPSIS
  217.  
  218.   $filter = POE::Filter::Reference->new();
  219.   $arrayref_of_perl_references =
  220.     $filter->get($arrayref_of_raw_chunks_from_driver);
  221.   $arrayref_of_serialized_perl_references =
  222.      $filter->put($arrayref_of_perl_references);
  223.  
  224. =head1 DESCRIPTION
  225.  
  226. This filter packages referenced data for writing to a file or socket.
  227. Upon receipt of packaged data, it reconstitutes the original structure
  228. and returns a reference to it.  This provides a handy way to ship data
  229. between processes and systems.
  230.  
  231. =head1 PUBLIC FILTER METHODS
  232.  
  233. =over 2
  234.  
  235. =item new SERIALIZER, COMPRESSION
  236.  
  237. =item new SERIALIZER
  238.  
  239. =item new
  240.  
  241. new() creates and initializes a reference filter.  It accepts two
  242. optional parameters: A serializer and a flag that determines whether
  243. Compress::Zlib will be used to compress serialized data.
  244.  
  245. Serializers are modelled after Storable.  Storable has a nfreeze()
  246. function which translates referenced data into strings suitable for
  247. shipping across sockets.  It also contains a freeze() method which is
  248. less desirable since it doesn't take network byte ordering into
  249. effect.  Finally there's thaw() which translates frozen strings back
  250. into data.
  251.  
  252. SERIALIZER may be a package name or an object reference, or it may be
  253. omitted altogether.
  254.  
  255. If SERIALIZER is a package name, it is assumed that the package will
  256. have a thaw() function as well as etither an nfreeze() or a freeze()
  257. function.
  258.  
  259.   # Use Storable explicitly, specified by package name.
  260.   my $filter = POE::Filter::Reference->new("Storable");
  261.  
  262.   # Use YAML, perhaps to pass data to programs not written with POE or
  263.   # even in Perl at all.
  264.   my $filter = POE::Filter::Reference->new("YAML");
  265.  
  266. If SERIALIZER is an object reference, it's assumed to have a thaw()
  267. method as well as either an nfreeze() or freeze() method.
  268.  
  269.   # Use an object.
  270.   my $filter = POE::Filter::Reference->new($object);
  271.  
  272. If SERIALIZER is omitted or undef, the Reference filter will try to
  273. use Storable, FreezeThaw, and YAML.  Filter::Reference will die if it
  274. cannot find one of these serializers.
  275.  
  276.   # Use the default filter (either Storable, FreezeThaw, or YAML).
  277.   my $filter = POE::Filter::Reference->new();
  278.  
  279. Filter::Reference will try to compress frozen strings and uncompress
  280. them before thawing if COMPRESSION is true.  It uses Compress::Zlib
  281. for this, but it works fine even without Zlib as long as COMPRESSION
  282. is false.
  283.  
  284. An object serializer must have a thaw() method.  It also must have
  285. either a freeze() or nfreeze() method.  If it has both freeze() and
  286. nfreeze(), then Filter::Reference will use nfreeze() for portability.
  287. The thaw() method accepts $self and a scalar; it should return a
  288. reference to the reconstituted data.  The freeze() and nfreeze()
  289. methods receive $self and a reference; they should return a scalar
  290. with the reference's serialized representation.
  291.  
  292. If the serializer parameter is undef, a default one will be used.
  293. This lets programs specify compression without having to worry about
  294. naming a serializer.
  295.  
  296. For example:
  297.  
  298.   # Use the default filter (either Storable, FreezeThaw, or YAML).
  299.   my $filter = POE::Filter::Reference->new();
  300.  
  301.   # Use an object, with compression.
  302.   my $filter = POE::Filter::Reference->new($object, 1);
  303.  
  304.   # Use the default serializer, with compression.
  305.   my $filter = POE::Filter::Reference->new(undef, 1);
  306.  
  307. The new() method will try to require any packages it needs.
  308.  
  309. The default behavior is to try Storable first, FreezeThaw second, YAML
  310. third, and finally fail.
  311.  
  312. =item get [ FROZEN_DATA ]
  313.  
  314. The get() method thaws a referenced list of FROZEN_DATA chunks back
  315. into references.  References will be blessed, if necessary.  If the
  316. references points to an object, be sure the receiving end has used the
  317. appropriate modules before calling their methods.
  318.  
  319.   $thingrefs = $filter_reference->get(\@stream_chunks);
  320.   foreach (@$thingrefs) {
  321.     ...;
  322.   }
  323.  
  324. =item put [ REFERENCES ]
  325.  
  326. The put() method freezes one or more REFERENCES and returns their
  327. serialized, streamable representations as a list reference.
  328.  
  329.   $listref = $filter_reference->put([ \%thing_one, \@thing_two ]);
  330.   foreach (@$listref) {
  331.     ...;
  332.   }
  333.  
  334. =back
  335.  
  336. =head1 SEE ALSO
  337.  
  338. POE::Filter.
  339.  
  340. The SEE ALSO section in L<POE> contains a table of contents covering
  341. the entire POE distribution.
  342.  
  343. =head1 BUGS
  344.  
  345. Whatever is used to freeze and thaw data should be aware of potential
  346. differences in system byte orders.  Also be careful that the same
  347. freeze/thaw code is used on both sides of a socket.  That includes
  348. even the most minor version differences.
  349.  
  350. =head1 AUTHORS & COPYRIGHTS
  351.  
  352. The Reference filter was contributed by Arturn Bergman, with changes
  353. by Philip Gwyn.
  354.  
  355. Please see L<POE> for more information about authors and contributors.
  356.  
  357. =cut
  358.