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
diff --git a/apps/buffering.c b/apps/buffering.c
index 18f3ba6..5fd8c24 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -970,6 +970,45 @@
     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 @@
     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 @@
     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;
 }
 
 /*