4 This file is part of PulseAudio.
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <pulse/xmalloc.h>
37 pa_memchunk leftover, current;
40 pa_mcalign *pa_mcalign_new(size_t base) {
44 m = pa_xnew(pa_mcalign, 1);
47 pa_memchunk_reset(&m->leftover);
48 pa_memchunk_reset(&m->current);
53 void pa_mcalign_free(pa_mcalign *m) {
56 if (m->leftover.memblock)
57 pa_memblock_unref(m->leftover.memblock);
59 if (m->current.memblock)
60 pa_memblock_unref(m->current.memblock);
65 void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
70 assert(c->length > 0);
72 assert(!m->current.memblock);
74 /* Append to the leftover memory block */
75 if (m->leftover.memblock) {
78 if (m->leftover.memblock == c->memblock &&
79 m->leftover.index + m->leftover.length == c->index) {
82 m->leftover.length += c->length;
84 /* If the new chunk is larger than m->base, move it to current */
85 if (m->leftover.length >= m->base) {
86 m->current = m->leftover;
87 pa_memchunk_reset(&m->leftover);
94 assert(m->leftover.length < m->base);
95 l = m->base - m->leftover.length;
100 /* Can we use the current block? */
101 pa_memchunk_make_writable(&m->leftover, m->base);
103 memcpy((uint8_t*) m->leftover.memblock->data + m->leftover.index + m->leftover.length, (uint8_t*) c->memblock->data + c->index, l);
104 m->leftover.length += l;
106 assert(m->leftover.length <= m->base && m->leftover.length <= m->leftover.memblock->length);
109 /* Save the remainder of the memory block */
111 m->current.index += l;
112 m->current.length -= l;
113 pa_memblock_ref(m->current.memblock);
117 /* Nothing to merge or copy, just store it */
119 if (c->length >= m->base)
124 pa_memblock_ref(c->memblock);
128 int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) {
132 /* First test if there's a leftover memory block available */
133 if (m->leftover.memblock) {
134 assert(m->leftover.length > 0 && m->leftover.length <= m->base);
136 /* The leftover memory block is not yet complete */
137 if (m->leftover.length < m->base)
140 /* Return the leftover memory block */
142 pa_memchunk_reset(&m->leftover);
144 /* If the current memblock is too small move it the leftover */
145 if (m->current.memblock && m->current.length < m->base) {
146 m->leftover = m->current;
147 pa_memchunk_reset(&m->current);
153 /* Now let's see if there is other data available */
154 if (m->current.memblock) {
156 assert(m->current.length >= m->base);
158 /* The length of the returned memory block */
159 l = m->current.length;
164 /* Prepare the returned block */
166 pa_memblock_ref(c->memblock);
169 /* Drop that from the current memory block */
170 assert(l <= m->current.length);
171 m->current.index += l;
172 m->current.length -= l;
174 /* In case the whole block was dropped ... */
175 if (m->current.length == 0)
176 pa_memblock_unref(m->current.memblock);
178 /* Move the raimainder to leftover */
179 assert(m->current.length < m->base && !m->leftover.memblock);
181 m->leftover = m->current;
184 pa_memchunk_reset(&m->current);
189 /* There's simply nothing */
194 size_t pa_mcalign_csize(pa_mcalign *m, size_t l) {
198 assert(!m->current.memblock);
200 if (m->leftover.memblock)
201 l += m->leftover.length;
203 return (l/m->base)*m->base;