# HG changeset patch # User Rik and John W. Eaton # Date 1393014482 18000 # Node ID fdd27f68b0118c097cd88bf5b84a77f2c5b7f0ea # Parent bcc88f8f071d7ed4263cc05f2d3a5fed3819f77e handle fread skip parameter correctly (bug #41648) * oct-stream.cc (octave_stream::read): Decide whether to skip based on current number of elements read, not total. Correctly handle case of reading partial blocks when there is a repeat cound. Skip to EOF if the full skip is beyond EOF. * io.tst: New test. diff -r bcc88f8f071d -r fdd27f68b011 libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Thu Jan 16 16:26:56 2014 -0500 +++ b/libinterp/corefcn/oct-stream.cc Fri Feb 21 15:28:02 2014 -0500 @@ -3260,6 +3260,14 @@ while (is && ! is.eof () && (read_to_eof || count < elts_to_read)) { + if (! read_to_eof) + { + octave_idx_type remaining_elts = elts_to_read - count; + + if (remaining_elts < input_buf_elts) + input_buf_size = remaining_elts * input_elt_size; + } + char *input_buf = new char [input_buf_size]; is.read (input_buf, input_buf_size); @@ -3268,15 +3276,35 @@ char_count += gcount; - count += gcount / input_elt_size; + size_t nel = gcount / input_elt_size; + + count += nel; input_buf_list.push_back (input_buf); - if (is && skip != 0 && count == block_size) + if (is && skip != 0 && nel == block_size) { - int seek_status = seek (skip, SEEK_CUR); - - if (seek_status < 0) + // Seek to skip. If skip would move past EOF, + // position at EOF. + + off_t orig_pos = tell (); + + seek (0, SEEK_END); + + off_t eof_pos = tell (); + + // Is it possible for this to fail to return us to + // the original position? + seek (orig_pos, SEEK_SET); + + size_t remaining = eof_pos - orig_pos; + + if (remaining < skip) + seek (0, SEEK_END); + else + seek (skip, SEEK_CUR); + + if (! is) break; } } diff -r bcc88f8f071d -r fdd27f68b011 test/io.tst --- a/test/io.tst Thu Jan 16 16:26:56 2014 -0500 +++ b/test/io.tst Fri Feb 21 15:28:02 2014 -0500 @@ -547,3 +547,25 @@ %! assert (data, [25185, 26213; 25699, 0]); %! assert (count, 3); %! fclose (id); + +%!test +%! id = tmpfile (); +%! fwrite (id, char (0:15)); +%! frewind (id); +%! [data, count] = fread (id, inf, "2*uint8", 2); +%! assert (data, [0; 1; 4; 5; 8; 9; 12; 13]); +%! assert (count, 8); +%! frewind (id); +%! [data, count] = fread (id, 3, "2*uint8", 3); +%! assert (data, [0; 1; 5]); +%! assert (count, 3); +%! [data, count] = fread (id, 3, "2*uint8", 3); +%! assert (data, [6; 7; 11]); +%! assert (count, 3); +%! [data, count] = fread (id, 3, "2*uint8", 3); +%! assert (data, [12; 13]); +%! assert (count, 2); +%! [data, count] = fread (id, 3, "2*uint8", 3); +%! assert (data, []); +%! assert (count, 0); +%! fclose (id);