diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/lib/buflib.c | 48 | ||||
-rw-r--r-- | apps/plugins/lib/buflib.h | 5 |
2 files changed, 53 insertions, 0 deletions
diff --git a/apps/plugins/lib/buflib.c b/apps/plugins/lib/buflib.c index 514479600e..ddfc82c521 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) | |||
61 | ctx->last_handle = bd_buf + size; | 61 | ctx->last_handle = bd_buf + size; |
62 | ctx->first_free_handle = bd_buf + size - 1; | 62 | ctx->first_free_handle = bd_buf + size - 1; |
63 | ctx->first_free_block = bd_buf; | 63 | ctx->first_free_block = bd_buf; |
64 | ctx->buf_start = bd_buf; | ||
64 | /* A marker is needed for the end of allocated data, to make sure that it | 65 | /* A marker is needed for the end of allocated data, to make sure that it |
65 | * does not collide with the handle table, and to detect end-of-buffer. | 66 | * does not collide with the handle table, and to detect end-of-buffer. |
66 | */ | 67 | */ |
@@ -167,6 +168,53 @@ buflib_compact(struct buflib_context *ctx) | |||
167 | return ret || shift; | 168 | return ret || shift; |
168 | } | 169 | } |
169 | 170 | ||
171 | /* Shift buffered items by size units, and update handle pointers. The shift | ||
172 | * value must be determined to be safe *before* calling. | ||
173 | */ | ||
174 | static void | ||
175 | buflib_buffer_shift(struct buflib_context *ctx, int shift) | ||
176 | { | ||
177 | rb->memmove(ctx->buf_start + shift, ctx->buf_start, | ||
178 | (ctx->alloc_end - ctx->buf_start) * sizeof(union buflib_data)); | ||
179 | union buflib_data *ptr; | ||
180 | for (ptr = ctx->last_handle; ptr < ctx->handle_table; ptr++) | ||
181 | if (ptr->ptr) | ||
182 | ptr->ptr += shift; | ||
183 | ctx->first_free_block += shift; | ||
184 | ctx->buf_start += shift; | ||
185 | ctx->alloc_end += shift; | ||
186 | } | ||
187 | |||
188 | /* Shift buffered items up by size bytes, or as many as possible if size == 0. | ||
189 | * Set size to the number of bytes freed. | ||
190 | */ | ||
191 | void* | ||
192 | buflib_buffer_out(struct buflib_context *ctx, size_t *size) | ||
193 | { | ||
194 | if (!ctx->compact) | ||
195 | buflib_compact(ctx); | ||
196 | size_t avail = ctx->last_handle - ctx->alloc_end; | ||
197 | size_t avail_b = avail * sizeof(union buflib_data); | ||
198 | if (*size && *size < avail_b) | ||
199 | { | ||
200 | avail = (*size + sizeof(union buflib_data) - 1) | ||
201 | / sizeof(union buflib_data); | ||
202 | avail_b = avail * sizeof(union buflib_data); | ||
203 | } | ||
204 | *size = avail_b; | ||
205 | void *ret = ctx->buf_start; | ||
206 | buflib_buffer_shift(ctx, avail); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | /* Shift buffered items down by size bytes */ | ||
211 | void | ||
212 | buflib_buffer_in(struct buflib_context *ctx, int size) | ||
213 | { | ||
214 | size /= sizeof(union buflib_data); | ||
215 | buflib_buffer_shift(ctx, -size); | ||
216 | } | ||
217 | |||
170 | /* Allocate a buffer of size bytes, returning a handle for it */ | 218 | /* Allocate a buffer of size bytes, returning a handle for it */ |
171 | int | 219 | int |
172 | buflib_alloc(struct buflib_context *ctx, size_t size) | 220 | buflib_alloc(struct buflib_context *ctx, size_t size) |
diff --git a/apps/plugins/lib/buflib.h b/apps/plugins/lib/buflib.h index ddadb1b9a9..d4ef4af9ff 100644 --- a/apps/plugins/lib/buflib.h +++ b/apps/plugins/lib/buflib.h | |||
@@ -38,6 +38,7 @@ struct buflib_context | |||
38 | union buflib_data *first_free_handle; | 38 | union buflib_data *first_free_handle; |
39 | union buflib_data *last_handle; | 39 | union buflib_data *last_handle; |
40 | union buflib_data *first_free_block; | 40 | union buflib_data *first_free_block; |
41 | union buflib_data *buf_start; | ||
41 | union buflib_data *alloc_end; | 42 | union buflib_data *alloc_end; |
42 | bool compact; | 43 | bool compact; |
43 | }; | 44 | }; |
@@ -45,6 +46,10 @@ struct buflib_context | |||
45 | void buflib_init(struct buflib_context *context, void *buf, size_t size); | 46 | void buflib_init(struct buflib_context *context, void *buf, size_t size); |
46 | int buflib_alloc(struct buflib_context *context, size_t size); | 47 | int buflib_alloc(struct buflib_context *context, size_t size); |
47 | void buflib_free(struct buflib_context *context, int handle); | 48 | void buflib_free(struct buflib_context *context, int handle); |
49 | void* buflib_buffer_out(struct buflib_context *ctx, size_t *size); | ||
50 | void buflib_buffer_in(struct buflib_context *ctx, int size); | ||
51 | |||
52 | |||
48 | 53 | ||
49 | /* always_inline is due to this not getting inlined when not optimizing, which | 54 | /* always_inline is due to this not getting inlined when not optimizing, which |
50 | * leads to an unresolved reference since it doesn't exist as a non-inline | 55 | * leads to an unresolved reference since it doesn't exist as a non-inline |