summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/buflib.c
diff options
context:
space:
mode:
authorAndrew Mahone <andrew.mahone@gmail.com>2009-05-16 00:45:08 +0000
committerAndrew Mahone <andrew.mahone@gmail.com>2009-05-16 00:45:08 +0000
commitc909878f94073a364f9b3c75663080c044bff3b8 (patch)
tree9ba9ad0efd7def7c77816ddd83e9bf0eb1fa51b2 /apps/plugins/lib/buflib.c
parentd59bff092d461c013c0fed34ffa950e1f4ae2aa2 (diff)
downloadrockbox-c909878f94073a364f9b3c75663080c044bff3b8.zip
rockbox-c909878f94073a364f9b3c75663080c044bff3b8.tar.gz
rockbox-c909878f94073a364f9b3c75663080c044bff3b8.tar.bz2
rockbox-c909878f94073a364f9b3c75663080c044bff3b8.tar.xz
Extend buflib to support shifting space out off the buffer for other use, and returning space to the buffer.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20952 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/lib/buflib.c')
-rw-r--r--apps/plugins/lib/buflib.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/apps/plugins/lib/buflib.c b/apps/plugins/lib/buflib.c
index 5144796..ddfc82c 100644
--- a/apps/plugins/lib/buflib.c
+++ b/apps/plugins/lib/buflib.c
@@ -61,6 +61,7 @@ buflib_init(struct buflib_context *ctx, void *buf, size_t size)
ctx->last_handle = bd_buf + size;
ctx->first_free_handle = bd_buf + size - 1;
ctx->first_free_block = bd_buf;
+ ctx->buf_start = bd_buf;
/* A marker is needed for the end of allocated data, to make sure that it
* does not collide with the handle table, and to detect end-of-buffer.
*/
@@ -167,6 +168,53 @@ buflib_compact(struct buflib_context *ctx)
return ret || shift;
}
+/* Shift buffered items by size units, and update handle pointers. The shift
+ * value must be determined to be safe *before* calling.
+ */
+static void
+buflib_buffer_shift(struct buflib_context *ctx, int shift)
+{
+ rb->memmove(ctx->buf_start + shift, ctx->buf_start,
+ (ctx->alloc_end - ctx->buf_start) * sizeof(union buflib_data));
+ union buflib_data *ptr;
+ for (ptr = ctx->last_handle; ptr < ctx->handle_table; ptr++)
+ if (ptr->ptr)
+ ptr->ptr += shift;
+ ctx->first_free_block += shift;
+ ctx->buf_start += shift;
+ ctx->alloc_end += shift;
+}
+
+/* Shift buffered items up by size bytes, or as many as possible if size == 0.
+ * Set size to the number of bytes freed.
+ */
+void*
+buflib_buffer_out(struct buflib_context *ctx, size_t *size)
+{
+ if (!ctx->compact)
+ buflib_compact(ctx);
+ size_t avail = ctx->last_handle - ctx->alloc_end;
+ size_t avail_b = avail * sizeof(union buflib_data);
+ if (*size && *size < avail_b)
+ {
+ avail = (*size + sizeof(union buflib_data) - 1)
+ / sizeof(union buflib_data);
+ avail_b = avail * sizeof(union buflib_data);
+ }
+ *size = avail_b;
+ void *ret = ctx->buf_start;
+ buflib_buffer_shift(ctx, avail);
+ return ret;
+}
+
+/* Shift buffered items down by size bytes */
+void
+buflib_buffer_in(struct buflib_context *ctx, int size)
+{
+ size /= sizeof(union buflib_data);
+ buflib_buffer_shift(ctx, -size);
+}
+
/* Allocate a buffer of size bytes, returning a handle for it */
int
buflib_alloc(struct buflib_context *ctx, size_t size)