Commit cec507e8 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

stream: revector

parent 10bf15ba
...@@ -325,210 +325,157 @@ error: ...@@ -325,210 +325,157 @@ error:
return NULL; 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; block_t *block = *pp;
size_t copy = 0;
ssize_t ret = 0;
while (len > 0) if (block == NULL)
{ return -1;
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) if (len > block->i_buffer)
block = s->pf_block(s, &eof); len = block->i_buffer;
if (block == NULL) if (buf != NULL)
{ memcpy(buf, block->p_buffer, len);
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 (ret == 0) block->p_buffer += len;
break; block->i_buffer -= len;
if (ret < 0)
continue;
assert((size_t)ret <= len); if (block->i_buffer == 0)
if (buf != NULL) {
buf = (unsigned char *)buf + ret; block_Release(block);
len -= ret; *pp = NULL;
copy += ret;
} }
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; stream_priv_t *priv = (stream_priv_t *)s;
block_t *peek = priv->peek; ssize_t ret;
size_t copy = 0;
if (unlikely(len == 0)) if (vlc_killed())
return 0; return 0;
if (peek != NULL) if (s->pf_read != NULL)
{ {
copy = peek->i_buffer < len ? peek->i_buffer : len; assert(priv->block == NULL);
ret = s->pf_read(s, buf, len);
if (buf != NULL) return ret;
memcpy(buf, peek->p_buffer, copy); }
peek->p_buffer += copy; ret = vlc_stream_CopyBlock(&priv->block, buf, len);
peek->i_buffer -= copy; if (ret >= 0)
if (peek->i_buffer == 0) return ret;
{
block_Release(peek);
priv->peek = NULL;
}
if (buf != NULL) if (s->pf_block != NULL)
buf = (unsigned char *)buf + copy; {
len -= copy; bool eof = false;
priv->offset += copy;
if (len == 0) priv->block = s->pf_block(s, &eof);
return copy; 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); return 0;
if (ret < 0)
return ((copy > 0) ? (ssize_t)copy : ret);
copy += ret;
priv->offset += ret;
priv->eof = !ret;
return copy;
} }
ssize_t vlc_stream_ReadPartial(stream_t *s, void *buf, size_t len) ssize_t vlc_stream_ReadPartial(stream_t *s, void *buf, size_t len)
{ {
stream_priv_t *priv = (stream_priv_t *)s; 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; priv->offset += ret;
return ret;
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; ret = vlc_stream_ReadRaw(s, buf, len);
if (likely(len > 0)) if (ret > 0)
priv->eof = !ret; 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) while (len > 0)
{ {
bool eof; 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 (buf != NULL)
if (priv->block == NULL && eof) buf = (char *)buf + ret;
return 0; len -= ret;
} copied += ret;
else
return 0;
} }
return copied;
} }
ssize_t vlc_stream_Peek(stream_t *s, const uint8_t **restrict bufp, size_t len) ssize_t vlc_stream_Peek(stream_t *s, const uint8_t **restrict bufp, size_t len)
{ {
stream_priv_t *priv = (stream_priv_t *)s; 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; priv->block = NULL;
} }
if (priv->peek == NULL) if (peek == NULL)
{ {
block_t *peek = block_Alloc(len); peek = block_Alloc(len);
if (unlikely(peek == NULL)) if (unlikely(peek == NULL))
return VLC_ENOMEM; return VLC_ENOMEM;
*bufp = peek->p_buffer; peek->i_buffer = 0;
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;
} }
else
if (priv->peek->i_buffer < len) if (peek->i_buffer < len)
{ {
size_t avail = priv->peek->i_buffer; size_t avail = peek->i_buffer;
ssize_t ret;
block_t *peek = block_TryRealloc(priv->peek, 0, len); peek = block_TryRealloc(peek, 0, len);
if (unlikely(peek == NULL)) if (unlikely(peek == NULL))
return VLC_ENOMEM; return VLC_ENOMEM;
priv->peek = peek;
peek->i_buffer = avail; 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); ret = vlc_stream_ReadRaw(s, peek->p_buffer + avail, len - avail);
*bufp = peek->p_buffer; if (ret < 0)
if (ret >= 0) continue;
peek->i_buffer += ret;
return peek->i_buffer; peek->i_buffer += ret;
if (ret == 0)
return peek->i_buffer;
} }
/* Nothing to do */
*bufp = priv->peek->p_buffer;
return len; return len;
} }
...@@ -537,6 +484,12 @@ block_t *vlc_stream_ReadBlock(stream_t *s) ...@@ -537,6 +484,12 @@ block_t *vlc_stream_ReadBlock(stream_t *s)
stream_priv_t *priv = (stream_priv_t *)s; stream_priv_t *priv = (stream_priv_t *)s;
block_t *block; block_t *block;
if (vlc_killed())
{
priv->eof = true;
return NULL;
}
if (priv->peek != NULL) if (priv->peek != NULL)
{ {
block = priv->peek; block = priv->peek;
...@@ -554,24 +507,20 @@ block_t *vlc_stream_ReadBlock(stream_t *s) ...@@ -554,24 +507,20 @@ block_t *vlc_stream_ReadBlock(stream_t *s)
} }
else else
{ {
if (vlc_killed())
return NULL;
block = block_Alloc(4096); block = block_Alloc(4096);
if (unlikely(block == NULL)) if (unlikely(block == NULL))
return NULL; return NULL;
ssize_t ret = s->pf_read(s, block->p_buffer, block->i_buffer); ssize_t ret = s->pf_read(s, block->p_buffer, block->i_buffer);
if (ret >= 0) if (ret > 0)
{
block->i_buffer = ret; block->i_buffer = ret;
priv->eof = !ret;
}
else else
{ {
block_Release(block); block_Release(block);
block = NULL; block = NULL;
} }
priv->eof = !ret;
} }
if (block != NULL) if (block != NULL)
......
...@@ -79,7 +79,6 @@ int main(void) ...@@ -79,7 +79,6 @@ int main(void)
val = vlc_stream_Read(s, buf, sizeof (buf)); val = vlc_stream_Read(s, buf, sizeof (buf));
assert(val == 3); assert(val == 3);
assert(vlc_stream_Tell(s) == 3); assert(vlc_stream_Tell(s) == 3);
assert(!vlc_stream_Eof(s));
assert(memcmp(buf, "123", 3) == 0); assert(memcmp(buf, "123", 3) == 0);
val = vlc_stream_Read(s, buf, sizeof (buf)); val = vlc_stream_Read(s, buf, sizeof (buf));
assert(val == 0); assert(val == 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment