1use strict; 2use warnings; 3 4package Data::ParseBinary::Stream::StringRefReader; 5our @ISA = qw{Data::ParseBinary::Stream::Reader}; 6 7__PACKAGE__->_registerStreamType("StringRef"); 8 9sub new { 10 my ($class, $stringref) = @_; 11 my $self = { 12 data => $stringref, 13 location => 0, 14 length => length($$stringref), 15 }; 16 return bless $self, $class; 17} 18 19sub ReadBytes { 20 my ($self, $count) = @_; 21 die "not enought bytes in stream" if $self->{location} + $count > $self->{length}; 22 my $data = substr(${ $self->{data} }, $self->{location}, $count); 23 $self->{location} += $count; 24 return $data; 25} 26 27sub ReadBits { 28 my ($self, $bitcount) = @_; 29 return $self->_readBitsForByteStream($bitcount); 30} 31 32sub tell { 33 my $self = shift; 34 return $self->{location}; 35} 36 37sub seek { 38 my ($self, $newpos) = @_; 39 die "can not seek past string's end" if $newpos > $self->{length}; 40 $self->{location} = $newpos; 41} 42 43sub isBitStream { return 0 }; 44 45package Data::ParseBinary::Stream::StringReader; 46our @ISA = qw{Data::ParseBinary::Stream::StringRefReader}; 47 48__PACKAGE__->_registerStreamType("String"); 49 50sub new { 51 my ($class, $string) = @_; 52 return $class->SUPER::new(\$string); 53} 54 55package Data::ParseBinary::Stream::StringRefWriter; 56our @ISA = qw{Data::ParseBinary::Stream::Writer}; 57 58__PACKAGE__->_registerStreamType("StringRef"); 59 60sub new { 61 my ($class, $source) = @_; 62 if (not defined $source) { 63 my $data = ''; 64 $source = \$data; 65 } 66 my $self = { 67 data => $source, 68 offset => 0, # minus bytes from the end 69 }; 70 return bless $self, $class; 71} 72 73sub tell { 74 my $self = shift; 75 return length(${ $self->{data} }) - $self->{offset}; 76} 77 78sub seek { 79 my ($self, $newpos) = @_; 80 if ($newpos > length(${ $self->{data} })) { 81 $self->{offset} = 0; 82 ${ $self->{data} } .= "\0" x ($newpos - length(${ $self->{data} })) 83 } else { 84 $self->{offset} = length(${ $self->{data} }) - $newpos; 85 } 86} 87 88sub WriteBytes { 89 my ($self, $data) = @_; 90 if ($self->{offset} == 0) { 91 ${ $self->{data} } .= $data; 92 return length ${ $self->{data} }; 93 } 94 substr(${ $self->{data} }, -$self->{offset}, length($data), $data); 95 if ($self->{offset} <= length($data)) { 96 $self->{offset} = 0; 97 } else { 98 $self->{offset} = $self->{offset} - length($data); 99 } 100 return length(${ $self->{data} }) - $self->{offset}; 101} 102 103sub WriteBits { 104 my ($self, $bitdata) = @_; 105 return $self->_writeBitsForByteStream($bitdata); 106} 107 108sub Flush { 109 my $self = shift; 110 return $self->{data}; 111} 112 113sub isBitStream { return 0 }; 114 115package Data::ParseBinary::Stream::StringWriter; 116our @ISA = qw{Data::ParseBinary::Stream::StringRefWriter}; 117 118__PACKAGE__->_registerStreamType("String"); 119 120sub new { 121 my ($class, $source) = @_; 122 $source = '' unless defined $source; 123 return $class->SUPER::new(\$source); 124} 125 126sub Flush { 127 my $self = shift; 128 my $data = $self->SUPER::Flush(); 129 return $$data; 130} 131 132 1331;