| JSON-Streaming-Reader documentation | Contained in the JSON-Streaming-Reader distribution. |
JSON::Streaming::Reader::EventWrapper - Internal utility package for JSON::Streaming::Reader
This package is an internal implementation detail of JSON::Streaming::Reader. It is used to provide an API that looks like it blocks on top of a handle that doesn't block, so the parsing functions can pretend they have a blocking handle.
Instances of this class support enough of the IO::Handle interface to satisfy JSON::Streaming::Reader
and no more. In other words, they support only the read method and assume that the caller will only ever
want 1 character at a time.
This is not a public API. See the event-based API on JSON::Streaming::Reader, which is implemented in terms of this class. This class may go away in future versions, once refactoring renders it no longer necessary.
my $event_wrapper = JSON::Streaming::Reader::EventWrapper->new();
$event_wrapper->feed_buffer(\$string_of_data);
$event_wrapper->begin_reading();
my $char;
eval {
$event_wrapper->read($char, 1);
};
if ($@ == JSON::Streaming::Reader::EventWrapper::UNDERRUN) {
$event_wrapper->roll_back_reading();
}
else {
$event_wrapper->complete_reading();
# Do something with $char
}
| JSON-Streaming-Reader documentation | Contained in the JSON-Streaming-Reader distribution. |
package JSON::Streaming::Reader::EventWrapper; use strict; use warnings; # Make a dummy ref that can be used as a singleton exception to signal a buffer underrun. use constant UNDERRUN => {}; sub new { my ($class) = @_; my $self = bless {}, $class; $self->{buffer} = ""; $self->{offset} = 0; $self->{txn_offset} = undef; return $self; } sub feed_buffer { my ($self, $data) = @_; $self->{buffer} .= $$data; } sub signal_eof { my ($self) = @_; $self->{eof} = 1; } sub begin_reading { my ($self) = @_; $self->{txn_offset} = $self->{offset}; } sub roll_back_reading { my ($self) = @_; $self->{offset} = $self->{txn_offset}; $self->{txn_offset} = undef; } sub complete_reading { my ($self) = @_; $self->{txn_offset} = undef; $self->_trim_buffer(); } sub is_reading { return defined($_[0]->{txn_offset}); } sub read { my ($self) = @_; my $length = $_[2]; die "Can only read a single byte" if $length != 1; if ($self->{offset} < length($self->{buffer})) { $_[1] = substr($self->{buffer}, $self->{offset}, 1); $self->{offset}++; return 1; } else { if ($self->{eof}) { return 0; } else { #print STDERR "Underrun!\n"; #$self->_show_buffer(); die(UNDERRUN); } } } # Discard anything we've already read from the buffer sub _trim_buffer { my ($self) = @_; return if $self->{offset} == 0; $self->{buffer} = substr($self->{buffer}, $self->{offset}); $self->{offset} = 0; } # For debugging sub _show_buffer { my ($self, $offset) = @_; $offset = $self->{offset} unless defined($offset); print STDERR "Buffer: ", $self->{buffer}, "\n"; print STDERR " ", " " x $offset, "^\n"; } 1;