forked from len0rd/rockbox
Pull the size range checking and disk request into a separate function that both bufread and bufgetdata can use. Do better range checking to ensure that we don't get 'stuck' in the calls and warn with a logf if requests are made for which we cannot guarantee satisfaction.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15495 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
b848c683d6
commit
9821cce484
1 changed files with 48 additions and 51 deletions
|
|
@ -970,6 +970,45 @@ int bufadvance(int handle_id, off_t offset)
|
|||
return bufseek(handle_id, newpos);
|
||||
}
|
||||
|
||||
/* Used by bufread and bufgetdata to prepare the buffer and retrieve the
|
||||
* actual amount of data available for reading. This function explicitly
|
||||
* does not check the validity of the input handle. It does do range checks
|
||||
* on size and returns a valid (and explicit) amount of data for reading */
|
||||
static size_t prep_bufdata(const struct memory_handle *h, size_t size)
|
||||
{
|
||||
size_t avail = RINGBUF_SUB(h->widx, h->ridx);
|
||||
|
||||
if (avail == 0 && h->filerem == 0)
|
||||
/* File is finished reading */
|
||||
return 0;
|
||||
|
||||
if (size == 0 || size > h->available + h->filerem)
|
||||
size = h->available + h->filerem;
|
||||
|
||||
if (h->type == TYPE_PACKET_AUDIO && size > BUFFERING_DEFAULT_FILECHUNK)
|
||||
{
|
||||
/* If more than a filechunk is requested, log it and provide no more
|
||||
* than the amount of data on buffer or one file chunk */
|
||||
logf("data request > filechunk");
|
||||
size = MAX(avail,BUFFERING_DEFAULT_FILECHUNK);
|
||||
}
|
||||
|
||||
if (h->filerem > 0 && avail < size)
|
||||
{
|
||||
/* Data isn't ready. Request buffering */
|
||||
buf_request_buffer_handle(h->id);
|
||||
/* Wait for the data to be ready */
|
||||
do
|
||||
{
|
||||
sleep(1);
|
||||
avail = RINGBUF_SUB(h->widx, h->ridx);
|
||||
}
|
||||
while (h->filerem > 0 && avail < size);
|
||||
}
|
||||
|
||||
return MIN(size,avail);
|
||||
}
|
||||
|
||||
/* Copy data from the given handle to the dest buffer.
|
||||
Return the number of bytes copied or < 0 for failure (handle not found).
|
||||
The caller is blocked until the requested amount of data is available.
|
||||
|
|
@ -980,41 +1019,21 @@ ssize_t bufread(int handle_id, size_t size, void *dest)
|
|||
if (!h)
|
||||
return ERR_HANDLE_NOT_FOUND;
|
||||
|
||||
size_t ret;
|
||||
size_t avail = RINGBUF_SUB(h->widx, h->ridx);
|
||||
size = prep_bufdata(h, size);
|
||||
|
||||
if (avail == 0 && h->filerem == 0)
|
||||
/* File is finished reading */
|
||||
return 0;
|
||||
|
||||
if (h->filerem > 0 && (avail == 0 || avail < size))
|
||||
{
|
||||
/* Data isn't ready. Request buffering */
|
||||
buf_request_buffer_handle(handle_id);
|
||||
/* Wait for the data to be ready */
|
||||
do
|
||||
{
|
||||
sleep(1);
|
||||
avail = RINGBUF_SUB(h->widx, h->ridx);
|
||||
}
|
||||
while (h->filerem > 0 && (avail == 0 || avail < size));
|
||||
}
|
||||
|
||||
ret = MIN(size, avail);
|
||||
|
||||
if (h->ridx + ret > buffer_len)
|
||||
if (h->ridx + size > buffer_len)
|
||||
{
|
||||
/* the data wraps around the end of the buffer */
|
||||
size_t read = buffer_len - h->ridx;
|
||||
memcpy(dest, &buffer[h->ridx], read);
|
||||
memcpy(dest+read, buffer, ret - read);
|
||||
memcpy(dest+read, buffer, size - read);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(dest, &buffer[h->ridx], ret);
|
||||
memcpy(dest, &buffer[h->ridx], size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Update the "data" pointer to make the handle's data available to the caller.
|
||||
|
|
@ -1032,41 +1051,19 @@ ssize_t bufgetdata(int handle_id, size_t size, void **data)
|
|||
if (!h)
|
||||
return ERR_HANDLE_NOT_FOUND;
|
||||
|
||||
ssize_t ret;
|
||||
size_t avail = RINGBUF_SUB(h->widx, h->ridx);
|
||||
size = prep_bufdata(h, size);
|
||||
|
||||
if (avail == 0 && h->filerem == 0)
|
||||
/* File is finished reading */
|
||||
return 0;
|
||||
|
||||
if (h->filerem > 0 && (avail == 0 || avail < size))
|
||||
{
|
||||
/* Data isn't ready. Request buffering */
|
||||
buf_request_buffer_handle(handle_id);
|
||||
/* Wait for the data to be ready */
|
||||
do
|
||||
{
|
||||
sleep(1);
|
||||
avail = RINGBUF_SUB(h->widx, h->ridx);
|
||||
}
|
||||
while (h->filerem > 0 && (avail == 0 || avail < size));
|
||||
}
|
||||
|
||||
if (h->ridx + size > buffer_len && avail >= size)
|
||||
if (h->ridx + size > buffer_len)
|
||||
{
|
||||
/* the data wraps around the end of the buffer :
|
||||
use the guard buffer to provide the requested amount of data. */
|
||||
size_t copy_n = MIN(h->ridx + size - buffer_len, GUARD_BUFSIZE);
|
||||
memcpy(guard_buffer, (unsigned char *)buffer, copy_n);
|
||||
ret = buffer_len - h->ridx + copy_n;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = MIN(avail, buffer_len - h->ridx);
|
||||
size = buffer_len - h->ridx + copy_n;
|
||||
}
|
||||
|
||||
*data = &buffer[h->ridx];
|
||||
return ret;
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue