Mercurial > hg > octave-nkf
diff libinterp/corefcn/oct-stream.cc @ 18580:fdd27f68b011 stable
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.
author | Rik <rik@octave.org> and John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 21 Feb 2014 15:28:02 -0500 |
parents | a0abcf377ec5 |
children | bc31d9359cf9 0bdecd41b2dd |
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc +++ b/libinterp/corefcn/oct-stream.cc @@ -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; } }