#include #include #include #include #include "memchunk.h" void pa_memchunk_make_writable(struct pa_memchunk *c) { struct pa_memblock *n; assert(c && c->memblock && c->memblock->ref >= 1); if (c->memblock->ref == 1) return; n = pa_memblock_new(c->length); assert(n); memcpy(n->data, c->memblock->data+c->index, c->length); pa_memblock_unref(c->memblock); c->memblock = n; c->index = 0; } struct pa_mcalign { size_t base; struct pa_memchunk chunk; uint8_t *buffer; size_t buffer_fill; }; struct pa_mcalign *pa_mcalign_new(size_t base) { struct pa_mcalign *m; assert(base); m = malloc(sizeof(struct pa_mcalign)); assert(m); m->base = base; m->chunk.memblock = NULL; m->chunk.length = m->chunk.index = 0; m->buffer = NULL; m->buffer_fill = 0; return m; } void pa_mcalign_free(struct pa_mcalign *m) { assert(m); free(m->buffer); if (m->chunk.memblock) pa_memblock_unref(m->chunk.memblock); free(m); } void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { assert(m && c && !m->chunk.memblock && c->memblock && c->length); m->chunk = *c; pa_memblock_ref(m->chunk.memblock); } int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { assert(m && c && m->base > m->buffer_fill); int ret; if (!m->chunk.memblock) return -1; if (m->buffer_fill) { size_t l = m->base - m->buffer_fill; if (l > m->chunk.length) l = m->chunk.length; assert(m->buffer && l); memcpy(m->buffer + m->buffer_fill, m->chunk.memblock->data + m->chunk.index, l); m->buffer_fill += l; m->chunk.index += l; m->chunk.length -= l; if (m->chunk.length == 0) { m->chunk.length = m->chunk.index = 0; pa_memblock_unref(m->chunk.memblock); m->chunk.memblock = NULL; } assert(m->buffer_fill <= m->base); if (m->buffer_fill == m->base) { c->memblock = pa_memblock_new_dynamic(m->buffer, m->base); assert(c->memblock); c->index = 0; c->length = m->base; m->buffer = NULL; m->buffer_fill = 0; return 0; } return -1; } m->buffer_fill = m->chunk.length % m->base; if (m->buffer_fill) { assert(!m->buffer); m->buffer = malloc(m->base); assert(m->buffer); m->chunk.length -= m->buffer_fill; memcpy(m->buffer, m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill); } if (m->chunk.length) { *c = m->chunk; pa_memblock_ref(c->memblock); ret = 0; } else ret = -1; m->chunk.length = m->chunk.index = 0; pa_memblock_unref(m->chunk.memblock); m->chunk.memblock = NULL; return ret; }