diff --git a/src/input/stream.c b/src/input/stream.c index 8a1027f759223b59fea8ad6192ae57eea8429938..d12f8d95f5dd7a18258ef967320f2418eae3d346 100644 --- a/src/input/stream.c +++ b/src/input/stream.c @@ -325,210 +325,157 @@ error: return NULL; } -static ssize_t vlc_stream_ReadRaw(stream_t *s, void *buf, size_t len) +static ssize_t vlc_stream_CopyBlock(block_t **restrict pp, + void *buf, size_t len) { - stream_priv_t *priv = (stream_priv_t *)s; - size_t copy = 0; - ssize_t ret = 0; + block_t *block = *pp; - while (len > 0) - { - if (vlc_killed()) - ret = 0; - else if (s->pf_read != NULL) - { - assert(priv->block == NULL); - ret = s->pf_read(s, buf, len); - } - else if (s->pf_block != NULL) - { - block_t *block = priv->block; - bool eof = false; + if (block == NULL) + return -1; - if (block == NULL) - block = s->pf_block(s, &eof); + if (len > block->i_buffer) + len = block->i_buffer; - if (block == NULL) - { - assert(priv->block == NULL); - ret = eof ? 0 : -1; - } - else if (block->i_buffer <= len) - { - if (buf != NULL) - memcpy(buf, block->p_buffer, block->i_buffer); - ret = block->i_buffer; - block_Release(block); - priv->block = NULL; - } - else - { - if (buf != NULL) - memcpy(buf, block->p_buffer, len); - ret = len; - block->p_buffer += len; - block->i_buffer -= len; - priv->block = block; - } - } - else - ret = 0; + if (buf != NULL) + memcpy(buf, block->p_buffer, len); - if (ret == 0) - break; - if (ret < 0) - continue; + block->p_buffer += len; + block->i_buffer -= len; - assert((size_t)ret <= len); - if (buf != NULL) - buf = (unsigned char *)buf + ret; - len -= ret; - copy += ret; + if (block->i_buffer == 0) + { + block_Release(block); + *pp = NULL; } - return copy; + return likely(len > 0) ? (ssize_t)len : -1; } -ssize_t vlc_stream_Read(stream_t *s, void *buf, size_t len) +static ssize_t vlc_stream_ReadRaw(stream_t *s, void *buf, size_t len) { stream_priv_t *priv = (stream_priv_t *)s; - block_t *peek = priv->peek; - size_t copy = 0; + ssize_t ret; - if (unlikely(len == 0)) + if (vlc_killed()) return 0; - if (peek != NULL) + if (s->pf_read != NULL) { - copy = peek->i_buffer < len ? peek->i_buffer : len; - - if (buf != NULL) - memcpy(buf, peek->p_buffer, copy); + assert(priv->block == NULL); + ret = s->pf_read(s, buf, len); + return ret; + } - peek->p_buffer += copy; - peek->i_buffer -= copy; - if (peek->i_buffer == 0) - { - block_Release(peek); - priv->peek = NULL; - } + ret = vlc_stream_CopyBlock(&priv->block, buf, len); + if (ret >= 0) + return ret; - if (buf != NULL) - buf = (unsigned char *)buf + copy; - len -= copy; - priv->offset += copy; + if (s->pf_block != NULL) + { + bool eof = false; - if (len == 0) - return copy; + priv->block = s->pf_block(s, &eof); + ret = vlc_stream_CopyBlock(&priv->block, buf, len); + if (ret >= 0) + return ret; + return eof ? 0 : -1; } - ssize_t ret = vlc_stream_ReadRaw(s, buf, len); - if (ret < 0) - return ((copy > 0) ? (ssize_t)copy : ret); - copy += ret; - priv->offset += ret; - priv->eof = !ret; - return copy; + return 0; } ssize_t vlc_stream_ReadPartial(stream_t *s, void *buf, size_t len) { stream_priv_t *priv = (stream_priv_t *)s; + ssize_t ret; - for (;;) + ret = vlc_stream_CopyBlock(&priv->peek, buf, len); + if (ret >= 0) { - size_t avail = 0; - - if (priv->peek != NULL) - avail += priv->peek->i_buffer; - if (priv->block != NULL) - avail += priv->block->i_buffer; - if (avail > 0) - return vlc_stream_Read(s, buf, (avail < len) ? avail : len); - - if (s->pf_read != NULL) - { - ssize_t ret = s->pf_read(s, buf, len); - if (ret < 0) - return ret; + priv->offset += ret; + return ret; + } - priv->offset += ret; - if (likely(len > 0)) - priv->eof = !ret; + ret = vlc_stream_ReadRaw(s, buf, len); + if (ret > 0) + priv->offset += ret; + if (ret == 0) + priv->eof = len != 0; + return ret; +} - return ret; - } +ssize_t vlc_stream_Read(stream_t *s, void *buf, size_t len) +{ + size_t copied = 0; - if (s->pf_block != NULL) - { - bool eof; + while (len > 0) + { + ssize_t ret = vlc_stream_ReadPartial(s, buf, len); + if (ret < 0) + continue; + if (ret == 0) + break; - priv->block = s->pf_block(s, &eof); - if (priv->block == NULL && eof) - return 0; - } - else - return 0; + if (buf != NULL) + buf = (char *)buf + ret; + len -= ret; + copied += ret; } + + return copied; } ssize_t vlc_stream_Peek(stream_t *s, const uint8_t **restrict bufp, size_t len) { stream_priv_t *priv = (stream_priv_t *)s; + block_t *peek; - if (priv->peek == NULL) + peek = priv->peek; + if (peek == NULL) { - priv->peek = priv->block; + peek = priv->block; + priv->peek = peek; priv->block = NULL; } - if (priv->peek == NULL) + if (peek == NULL) { - block_t *peek = block_Alloc(len); + peek = block_Alloc(len); if (unlikely(peek == NULL)) return VLC_ENOMEM; - *bufp = peek->p_buffer; - - if (unlikely(len == 0)) - { - priv->peek = peek; - return 0; - } - - ssize_t ret = vlc_stream_ReadRaw(s, peek->p_buffer, len); - if (ret < 0) - { - block_Release(peek); - return ret; - } - - peek->i_buffer = ret; - priv->peek = peek; - return ret; + peek->i_buffer = 0; } - - if (priv->peek->i_buffer < len) + else + if (peek->i_buffer < len) { - size_t avail = priv->peek->i_buffer; - ssize_t ret; + size_t avail = peek->i_buffer; - block_t *peek = block_TryRealloc(priv->peek, 0, len); + peek = block_TryRealloc(peek, 0, len); if (unlikely(peek == NULL)) return VLC_ENOMEM; - priv->peek = peek; peek->i_buffer = avail; + } + + priv->peek = peek; + *bufp = peek->p_buffer; + + while (peek->i_buffer < len) + { + size_t avail = peek->i_buffer; + ssize_t ret; ret = vlc_stream_ReadRaw(s, peek->p_buffer + avail, len - avail); - *bufp = peek->p_buffer; - if (ret >= 0) - peek->i_buffer += ret; - return peek->i_buffer; + if (ret < 0) + continue; + + peek->i_buffer += ret; + + if (ret == 0) + return peek->i_buffer; } - /* Nothing to do */ - *bufp = priv->peek->p_buffer; return len; } @@ -537,6 +484,12 @@ block_t *vlc_stream_ReadBlock(stream_t *s) stream_priv_t *priv = (stream_priv_t *)s; block_t *block; + if (vlc_killed()) + { + priv->eof = true; + return NULL; + } + if (priv->peek != NULL) { block = priv->peek; @@ -554,24 +507,20 @@ block_t *vlc_stream_ReadBlock(stream_t *s) } else { - if (vlc_killed()) - return NULL; - block = block_Alloc(4096); if (unlikely(block == NULL)) return NULL; ssize_t ret = s->pf_read(s, block->p_buffer, block->i_buffer); - if (ret >= 0) - { + if (ret > 0) block->i_buffer = ret; - priv->eof = !ret; - } else { block_Release(block); block = NULL; } + + priv->eof = !ret; } if (block != NULL) diff --git a/test/src/input/stream_fifo.c b/test/src/input/stream_fifo.c index f6c9709d269a615613f86cdb6c8a21073bf212f1..4c9dce195f14775acffe8174b17c075de23e1802 100644 --- a/test/src/input/stream_fifo.c +++ b/test/src/input/stream_fifo.c @@ -79,7 +79,6 @@ int main(void) val = vlc_stream_Read(s, buf, sizeof (buf)); assert(val == 3); assert(vlc_stream_Tell(s) == 3); - assert(!vlc_stream_Eof(s)); assert(memcmp(buf, "123", 3) == 0); val = vlc_stream_Read(s, buf, sizeof (buf)); assert(val == 0);