]> code.delx.au - pulseaudio/blob - polyp/memchunk.c
rename src to polyp
[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
33 void pa_memchunk_make_writable(struct pa_memchunk *c) {
34 struct pa_memblock *n;
35 assert(c && c->memblock && c->memblock->ref >= 1);
36
37 if (c->memblock->ref == 1)
38 return;
39
40 n = pa_memblock_new(c->length);
41 assert(n);
42 memcpy(n->data, c->memblock->data+c->index, c->length);
43 pa_memblock_unref(c->memblock);
44 c->memblock = n;
45 c->index = 0;
46 }
47
48
49 struct pa_mcalign {
50 size_t base;
51 struct pa_memchunk chunk;
52 uint8_t *buffer;
53 size_t buffer_fill;
54 };
55
56 struct pa_mcalign *pa_mcalign_new(size_t base) {
57 struct pa_mcalign *m;
58 assert(base);
59
60 m = malloc(sizeof(struct pa_mcalign));
61 assert(m);
62 m->base = base;
63 m->chunk.memblock = NULL;
64 m->chunk.length = m->chunk.index = 0;
65 m->buffer = NULL;
66 m->buffer_fill = 0;
67 return m;
68 }
69
70 void pa_mcalign_free(struct pa_mcalign *m) {
71 assert(m);
72
73 free(m->buffer);
74
75 if (m->chunk.memblock)
76 pa_memblock_unref(m->chunk.memblock);
77
78 free(m);
79 }
80
81 void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) {
82 assert(m && c && !m->chunk.memblock && c->memblock && c->length);
83
84 m->chunk = *c;
85 pa_memblock_ref(m->chunk.memblock);
86 }
87
88 int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) {
89 assert(m && c && m->base > m->buffer_fill);
90 int ret;
91
92 if (!m->chunk.memblock)
93 return -1;
94
95 if (m->buffer_fill) {
96 size_t l = m->base - m->buffer_fill;
97 if (l > m->chunk.length)
98 l = m->chunk.length;
99 assert(m->buffer && l);
100
101 memcpy(m->buffer + m->buffer_fill, m->chunk.memblock->data + m->chunk.index, l);
102 m->buffer_fill += l;
103 m->chunk.index += l;
104 m->chunk.length -= l;
105
106 if (m->chunk.length == 0) {
107 m->chunk.length = m->chunk.index = 0;
108 pa_memblock_unref(m->chunk.memblock);
109 m->chunk.memblock = NULL;
110 }
111
112 assert(m->buffer_fill <= m->base);
113 if (m->buffer_fill == m->base) {
114 c->memblock = pa_memblock_new_dynamic(m->buffer, m->base);
115 assert(c->memblock);
116 c->index = 0;
117 c->length = m->base;
118 m->buffer = NULL;
119 m->buffer_fill = 0;
120
121 return 0;
122 }
123
124 return -1;
125 }
126
127 m->buffer_fill = m->chunk.length % m->base;
128
129 if (m->buffer_fill) {
130 assert(!m->buffer);
131 m->buffer = malloc(m->base);
132 assert(m->buffer);
133 m->chunk.length -= m->buffer_fill;
134 memcpy(m->buffer, m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill);
135 }
136
137 if (m->chunk.length) {
138 *c = m->chunk;
139 pa_memblock_ref(c->memblock);
140 ret = 0;
141 } else
142 ret = -1;
143
144 m->chunk.length = m->chunk.index = 0;
145 pa_memblock_unref(m->chunk.memblock);
146 m->chunk.memblock = NULL;
147
148 return ret;
149 }