ssize_t rc;
int good = 0;
+ /* this condition may be unused, callers should also be checking it */
if (ig->error || ig->buf_eof)
return 0;
if (needed > ig->buf_size)
needed = ig->buf_size;
+ if (ig->read_ptr && ig->read_ptr < ig->read_end) {
+ size_t kept = ig->read_end - ig->read_ptr;
+
+ if (needed < kept) {
+ IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
+ return 1;
+ }
+
+ if (ig->read_ptr != ig->buffer)
+ memmove(ig->buffer, ig->read_ptr, kept);
+
+ good = 1; /* we have *something* available to read */
+ work = buf_start + kept;
+ needed -= kept;
+ }
+ else {
+ work = ig->buffer;
+ }
+
while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
work += rc;
good = 1;
if (!ig->buffer)
i_io_setup_buffer(ig);
- if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
+ if (!ig->read_ptr || size > ig->read_end - ig->read_ptr) {
if (ig->error) {
IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error set)\n"));
return -1;
#!perl -w
use strict;
-use Test::More tests => 110;
+use Test::More tests => 115;
# for SEEK_SET etc, Fcntl doesn't provide these in 5.005_03
use IO::Seekable;
# peek a bit
undef $buf;
- is($io->peekn(5120), substr($base, 4096, 4096),
+ is($io->peekn(5120), substr($base, 4096, 5120),
"peekn() 5120, which should exceed the buffer, and only read the left overs");
}
is($io->read2(10), substr($base, 0, 10),
"and that reading 10 gets the expected data");
}
+
+ { # small peekn then large peekn
+ my $work = $base;
+ my $pos = 0;
+ my $ops = '';
+ my $reader = sub {
+ my ($size) = @_;
+
+ my $req_size = $size;
+ # do small reads, to trigger a possible bug
+ if ($size > 10) {
+ $size = 10;
+ }
+
+ if ($pos + $size > length $work) {
+ $size = length($work) - $pos;
+ }
+
+ my $result = substr($work, $pos, $size);
+ $pos += $size;
+ $ops .= "R$req_size>$size;";
+
+ print "# read $req_size>$size\n";
+
+ return $result;
+ };
+ my $io = Imager::io_new_cb(undef, $reader, undef, undef);
+ ok($io, "small reader io");
+ is($io->peekn(25), substr($base, 0, 25), "peek 25");
+ is($ops, "R8192>10;R8182>10;R8172>10;",
+ "check we got the raw calls expected");
+ is($io->peekn(65), substr($base, 0, 65), "peek 65");
+ is($ops, "R8192>10;R8182>10;R8172>10;R8162>10;R8152>10;R8142>10;R8132>10;",
+ "check we got the raw calls expected");
+ }
}
Imager->close_log;