]> code.delx.au - pulseaudio/blob - polyp/memchunk.c
87b9c1bd3b0c72066869289e26b3cdec82d5e60a
[pulseaudio] / polyp / memchunk.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio 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 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <string.h>
30
31 #include "memchunk.h"
32 #include "xmalloc.h"
33
34 void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s) {
35 struct pa_memblock *n;
36 assert(c && c->memblock && c->memblock->ref >= 1);
37
38 if (c->memblock->ref == 1)
39 return;
40
41 n = pa_memblock_new(c->length, s);
42 assert(n);
43 memcpy(n->data, (uint8_t*) c->memblock->data+c->index, c->length);
44 pa_memblock_unref(c->memblock);
45 c->memblock = n;
46 c->index = 0;
47 }
48
49
50 struct pa_mcalign {
51 size_t base;
52 struct pa_memchunk chunk;
53 uint8_t *buffer;
54 size_t buffer_fill;
55 struct pa_memblock_stat *memblock_stat;
56 };
57
58 struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s) {
59 struct pa_mcalign *m;
60 assert(base);
61
62 m = pa_xmalloc(sizeof(struct pa_mcalign));
63 m->base = base;
64 m->chunk.memblock = NULL;
65 m->chunk.length = m->chunk.index = 0;
66 m->buffer = NULL;
67 m->buffer_fill = 0;
68 m->memblock_stat = s;
69 return m;
70 }
71
72 void pa_mcalign_free(struct pa_mcalign *m) {
73 assert(m);
74
75 pa_xfree(m->buffer);
76
77 if (m->chunk.memblock)
78 pa_memblock_unref(m->chunk.memblock);
79
80 pa_xfree(m);
81 }
82
83 void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) {
84 assert(m && c && !m->chunk.memblock && c->memblock && c->length);
85
86 m->chunk = *c;
87 pa_memblock_ref(m->chunk.memblock);
88 }
89
90 int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) {
91 int ret;
92 assert(m && c && m->base > m->buffer_fill);
93
94 if (!m->chunk.memblock)
95 return -1;
96
97 if (m->buffer_fill) {
98 size_t l = m->base - m->buffer_fill;
99 if (l > m->chunk.length)
100 l = m->chunk.length;
101 assert(m->buffer && l);
102
103 memcpy((uint8_t*) m->buffer + m->buffer_fill, (uint8_t*) m->chunk.memblock->data + m->chunk.index, l);
104 m->buffer_fill += l;
105 m->chunk.index += l;
106 m->chunk.length -= l;
107
108 if (m->chunk.length == 0) {
109 m->chunk.length = m->chunk.index = 0;
110 pa_memblock_unref(m->chunk.memblock);
111 m->chunk.memblock = NULL;
112 }
113
114 assert(m->buffer_fill <= m->base);
115 if (m->buffer_fill == m->base) {
116 c->memblock = pa_memblock_new_dynamic(m->buffer, m->base, m->memblock_stat);
117 assert(c->memblock);
118 c->index = 0;
119 c->length = m->base;
120 m->buffer = NULL;
121 m->buffer_fill = 0;
122
123 return 0;
124 }
125
126 return -1;
127 }
128
129 m->buffer_fill = m->chunk.length % m->base;
130
131 if (m->buffer_fill) {
132 assert(!m->buffer);
133 m->buffer = pa_xmalloc(m->base);
134 m->chunk.length -= m->buffer_fill;
135 memcpy(m->buffer, (uint8_t*) m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill);
136 }
137
138 if (m->chunk.length) {
139 *c = m->chunk;
140 pa_memblock_ref(c->memblock);
141 ret = 0;
142 } else
143 ret = -1;
144
145 m->chunk.length = m->chunk.index = 0;
146 pa_memblock_unref(m->chunk.memblock);
147 m->chunk.memblock = NULL;
148
149 return ret;
150 }