use strict; use warnings; package Data::ParseBinary::Stream::StringRefReader; our @ISA = qw{Data::ParseBinary::Stream::Reader}; __PACKAGE__->_registerStreamType("StringRef"); sub new { my ($class, $stringref) = @_; my $self = { data => $stringref, location => 0, length => length($$stringref), }; return bless $self, $class; } sub ReadBytes { my ($self, $count) = @_; die "not enought bytes in stream" if $self->{location} + $count > $self->{length}; my $data = substr(${ $self->{data} }, $self->{location}, $count); $self->{location} += $count; return $data; } sub ReadBits { my ($self, $bitcount) = @_; return $self->_readBitsForByteStream($bitcount); } sub tell { my $self = shift; return $self->{location}; } sub seek { my ($self, $newpos) = @_; die "can not seek past string's end" if $newpos > $self->{length}; $self->{location} = $newpos; } sub isBitStream { return 0 }; package Data::ParseBinary::Stream::StringReader; our @ISA = qw{Data::ParseBinary::Stream::StringRefReader}; __PACKAGE__->_registerStreamType("String"); sub new { my ($class, $string) = @_; return $class->SUPER::new(\$string); } package Data::ParseBinary::Stream::StringRefWriter; our @ISA = qw{Data::ParseBinary::Stream::Writer}; __PACKAGE__->_registerStreamType("StringRef"); sub new { my ($class, $source) = @_; if (not defined $source) { my $data = ''; $source = \$data; } my $self = { data => $source, offset => 0, # minus bytes from the end }; return bless $self, $class; } sub tell { my $self = shift; return length(${ $self->{data} }) - $self->{offset}; } sub seek { my ($self, $newpos) = @_; if ($newpos > length(${ $self->{data} })) { $self->{offset} = 0; ${ $self->{data} } .= "\0" x ($newpos - length(${ $self->{data} })) } else { $self->{offset} = length(${ $self->{data} }) - $newpos; } } sub WriteBytes { my ($self, $data) = @_; if ($self->{offset} == 0) { ${ $self->{data} } .= $data; return length ${ $self->{data} }; } substr(${ $self->{data} }, -$self->{offset}, length($data), $data); if ($self->{offset} <= length($data)) { $self->{offset} = 0; } else { $self->{offset} = $self->{offset} - length($data); } return length(${ $self->{data} }) - $self->{offset}; } sub WriteBits { my ($self, $bitdata) = @_; return $self->_writeBitsForByteStream($bitdata); } sub Flush { my $self = shift; return $self->{data}; } sub isBitStream { return 0 }; package Data::ParseBinary::Stream::StringWriter; our @ISA = qw{Data::ParseBinary::Stream::StringRefWriter}; __PACKAGE__->_registerStreamType("String"); sub new { my ($class, $source) = @_; $source = '' unless defined $source; return $class->SUPER::new(\$source); } sub Flush { my $self = shift; my $data = $self->SUPER::Flush(); return $$data; } 1;