summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-05-27 21:53:40 +0200
committerwm4 <wm4@nowhere>2013-06-16 22:05:09 +0200
commit4abec2f7b2021d493d1aeefba5419963e6da698b (patch)
treeddf791a6d3c9af8bd84c383a8938b3e5561eaef3 /stream
parent34a383664ad570b3a85a698f61c494d4ff449d9a (diff)
downloadmpv-4abec2f7b2021d493d1aeefba5419963e6da698b.tar.bz2
mpv-4abec2f7b2021d493d1aeefba5419963e6da698b.tar.xz
stream: add partial read function
This is a nice way to avoid an additional copy of the data when reading with stream_read().
Diffstat (limited to 'stream')
-rw-r--r--stream/stream.c44
-rw-r--r--stream/stream.h1
2 files changed, 28 insertions, 17 deletions
diff --git a/stream/stream.c b/stream/stream.c
index 60b3571b82..230f08a198 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -432,28 +432,38 @@ int stream_fill_buffer(stream_t *s)
return len;
}
+// Read between 1..buf_size bytes of data, return how much data has been read.
+// Return <= 0 on EOF, error, of if buf_size was 0.
+int stream_read_partial(stream_t *s, char *buf, int buf_size)
+{
+ assert(s->buf_pos <= s->buf_len);
+ assert(buf_size >= 0);
+ if (s->buf_pos == s->buf_len && buf_size > 0) {
+ s->buf_pos = s->buf_len = 0;
+ // Do a direct read, but only if there's no sector alignment requirement
+ // Also, small reads will be more efficient with buffering & copying
+ if (!s->sector_size && buf_size >= STREAM_BUFFER_SIZE)
+ return stream_read_unbuffered(s, buf, buf_size);
+ if (!stream_fill_buffer(s))
+ return 0;
+ }
+ int len = FFMIN(buf_size, s->buf_len - s->buf_pos);
+ memcpy(buf, &s->buffer[s->buf_pos], len);
+ s->buf_pos += len;
+ return len;
+}
+
int stream_read(stream_t *s, char *mem, int total)
{
int len = total;
while (len > 0) {
- int x;
- x = s->buf_len - s->buf_pos;
- if (x == 0) {
- if (!stream_fill_buffer(s))
- return total - len; // EOF
- x = s->buf_len - s->buf_pos;
- }
- if (s->buf_pos > s->buf_len)
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "stream_read: WARNING! s->buf_pos>s->buf_len\n");
- if (x > len)
- x = len;
- memcpy(mem, &s->buffer[s->buf_pos], x);
- s->buf_pos += x;
- mem += x;
- len -= x;
+ int read = stream_read_partial(s, mem, len);
+ if (read <= 0)
+ break; // EOF
+ mem += read;
+ len -= read;
}
- return total;
+ return total - len;
}
int stream_write_buffer(stream_t *s, unsigned char *buf, int len)
diff --git a/stream/stream.h b/stream/stream.h
index 12ef430b28..68e22725b6 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -301,6 +301,7 @@ inline static int64_t stream_tell(stream_t *s)
int stream_skip(stream_t *s, int64_t len);
int stream_seek(stream_t *s, int64_t pos);
int stream_read(stream_t *s, char *mem, int total);
+int stream_read_partial(stream_t *s, char *buf, int buf_size);
struct MPOpts;
/*