summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorBrandon Low <lostlogic@rockbox.org>2007-11-06 16:49:30 +0000
committerBrandon Low <lostlogic@rockbox.org>2007-11-06 16:49:30 +0000
commit9821cce484b14f6f7ecbfa6367c26ceab7ebe87e (patch)
tree0894800a40f79346d2621923d2470425b9b9ee55 /apps
parentb848c683d62e9cd506518a0c23944c6bfcbb9bfe (diff)
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
Diffstat (limited to 'apps')
-rw-r--r--apps/buffering.c85
1 files changed, 41 insertions, 44 deletions
diff --git a/apps/buffering.c b/apps/buffering.c
index 18f3ba6900..5fd8c24122 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -970,51 +970,70 @@ int bufadvance(int handle_id, off_t offset)
return bufseek(handle_id, newpos);
}
-/* 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.
-*/
-ssize_t bufread(int handle_id, size_t size, void *dest)
+/* 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)
{
- const struct memory_handle *h = find_handle(handle_id);
- if (!h)
- return ERR_HANDLE_NOT_FOUND;
-
- size_t ret;
size_t avail = RINGBUF_SUB(h->widx, h->ridx);
if (avail == 0 && h->filerem == 0)
/* File is finished reading */
return 0;
- if (h->filerem > 0 && (avail == 0 || avail < size))
+ 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(handle_id);
+ 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 == 0 || avail < size));
+ while (h->filerem > 0 && avail < size);
}
- ret = MIN(size, avail);
+ return MIN(size,avail);
+}
- if (h->ridx + ret > buffer_len)
+/* 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.
+*/
+ssize_t bufread(int handle_id, size_t size, void *dest)
+{
+ const struct memory_handle *h = find_handle(handle_id);
+ if (!h)
+ return ERR_HANDLE_NOT_FOUND;
+
+ size = prep_bufdata(h, size);
+
+ 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;
}
/*